diff --git a/TangDou/AcWing_TiGao/T3/Floyd/343.eddx b/TangDou/AcWing_TiGao/T3/Floyd/343.eddx new file mode 100644 index 0000000..303043a Binary files /dev/null and b/TangDou/AcWing_TiGao/T3/Floyd/343.eddx differ diff --git a/TangDou/AcWing_TiGao/T3/Floyd/343.md b/TangDou/AcWing_TiGao/T3/Floyd/343.md index b8a7eb0..90f283a 100644 --- a/TangDou/AcWing_TiGao/T3/Floyd/343.md +++ b/TangDou/AcWing_TiGao/T3/Floyd/343.md @@ -166,7 +166,7 @@ string getorder(){ > **解释**:确定所有元素次序后如何判断元素`i`在第几个位置呢?`f[i][j] = 1`表示`i < j`,因此计算下`i`小于元素的个数`cnt`,就可以判定`i`是第`cnt + 1`大的元素了 -#### $Code$ +#### $Code$ $O(N^3)$ ```cpp {.line-numbers} #include using namespace std; @@ -245,4 +245,96 @@ int main() { } return 0; } +``` + +### 三、优化版本 +$O(N^2)$ + +其实,由于每次新增加的一对$(a,b)$,只会更新与$a,b$有边连接的点,其它的无关点是没有影响的,如果加上一对$(a,b)$就去全新计算,无疑是存在浪费的,可以优化的。 + +怎么优化呢?核心思路就是$(a,b)$做为$floyd$算法的中继点即可,其它点不再被遍历做为中继点。 + +说人话就是: +① 遍历所有节点,找出所有小于$a$的节点$x$,那么$x$一定小于$b$。 +② 遍历所有节点,找出所有大于$b$的节点$x$,那么$a$一定小于$x$。 +③ 遍历所有节点,如果$x +using namespace std; + +const int N = 26; + +int n, m; +bool g[N][N]; +bool st[N]; + +int check() { + for (int i = 0; i < n; i++) + if (g[i][i]) return 2; // 矛盾 + + for (int i = 0; i < n; i++) + for (int j = 0; j < i; j++) + if (!g[i][j] && !g[j][i]) // 待继续 + return 0; + + return 1; // 找到顺序 +} +string getorder() { // 升序输出所有变量 + char s[26]; + for (int i = 0; i < n; i++) { + int cnt = 0; + // f[i][j] = 1表示i可以到达j (i< j) + for (int j = 0; j < n; j++) cnt += g[i][j]; // 比i大的有多少个 + // 举个栗子:i=0,表示字符A + // 比如比i大的有5个,共6个字符:ABCDEF + // n - cnt - 1 = 6-5-1 = 0,也就是A放在第一个输出的位置上, 之所以再-1,是因为下标从0开始 + s[n - cnt - 1] = i + 'A'; + } + + // 转s字符数组为字符串 + string res; + for (int i = 0; i < n; i++) res = res + s[i]; + return res; +} + +int main() { + while (cin >> n >> m, n || m) { + memset(g, 0, sizeof g); + + int type = 0, t; + for (int i = 1; i <= m; i++) { + char str[5]; + cin >> str; + int a = str[0] - 'A', b = str[2] - 'A'; + + // a> str; int a = str[0] - 'A', b = str[2] - 'A'; + // a