|
|
|
@ -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 <bits/stdc++.h>
|
|
|
|
|
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<a$,并且,$b<y$,那么$x<y$
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
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<b,那么,不需要完全的重新计算完整的传递闭包,只需要把与a,b相关的变更进行记录大小关系即可
|
|
|
|
|
if (!type) {
|
|
|
|
|
g[a][b] = 1;
|
|
|
|
|
for (int x = 0; x < n; x++) {
|
|
|
|
|
if (g[x][a]) g[x][b] = 1; // 所有比a小的x,一定比b小
|
|
|
|
|
if (g[b][x]) g[a][x] = 1; // 所有比b大的x,一定比a大
|
|
|
|
|
for (int y = 0; y < n; y++)
|
|
|
|
|
if (g[x][a] && g[b][y])
|
|
|
|
|
g[x][y] = 1;
|
|
|
|
|
}
|
|
|
|
|
type = check();
|
|
|
|
|
if (type) t = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!type)
|
|
|
|
|
puts("Sorted sequence cannot be determined.");
|
|
|
|
|
else if (type == 2)
|
|
|
|
|
printf("Inconsistency found after %d relations.\n", t);
|
|
|
|
|
else {
|
|
|
|
|
string ans = getorder(); // 输出升序排列的所有变量
|
|
|
|
|
printf("Sorted sequence determined after %d relations: %s.\n", t, ans.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|