You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 30, M = N * N;
int n, m;
int a[1050], b[1050]; // a[i]<b[i]
char s[N]; // 输入的偏序关系
int in[N], ind[N];
int d[N], dl;
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
/*
拓扑序
(1) 出队列节点数量小于n,表示有环,矛盾
(2) 出队列节点数量等于n,在过程中有2个或以上的点在队列中表示拓扑序并不唯一那么此时并不能确定所有点的顺序
(3) 出队列节点数量等于n,在过程中,队列中一直只有一个,拓扑序唯一
*/
int topsort() {
queue<int> q;
bool flag = 0;
for (int i = 0; i < n; i++) // 枚举每个节点,入度为零的入队列
if (in[i] == 0) q.push(i);
while (q.size()) {
/*
注意此处需要优先检查是不是有环即使检查到某个点有多个前序节点也并不表示它应该返回2因为此时也可能是一个环
因为一旦检查是环,就不必再录入新的大小关系的,是一个截止的标识!
总结:判断是不是拓扑序不唯一的标准是:
① 队列节点数量等于n
② 在过程中有2个或以上的点在队列中
如果只发现了②就着急返回拓扑序不唯一,就可能会掉入到是环的坑中!
*/
if (q.size() > 1) flag = 1;
int u = q.front();
q.pop();
d[++dl] = u; // 按出队列的顺序来记录由小到大的关系
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (--in[j] == 0) q.push(j);
}
}
// 有环
if (dl < n) return 1;
// 不确定
if (dl == n && flag) return 2;
// 已确定
return 3;
}
int main() {
// n个变量m个不等式也就是n 个节点m条边
while (~scanf("%d%d", &n, &m) && n | m) {
// 多组测试数据,需要初始化
// 链式前向星
memset(h, -1, sizeof h);
idx = 0;
// 入度数组初始化
memset(ind, 0, sizeof ind);
// 输入大小关系,'A'->0,...,'Z'->25
for (int i = 1; i <= m; i++) {
scanf("%s", s); // 通用格式 类似于: B<C
a[i] = s[0] - 'A', b[i] = s[2] - 'A'; // 用两个数组a[],b[]记录关系,表示a[i]<b[i]
}
bool flag = 1; // 是不是已经找出了全部的大于关系序列
// 逐个讨论每个大小关系
for (int i = 1; i <= m; i++) {
dl = 0; // 拓扑序输出数组清零
add(a[i], b[i]); // 建图
ind[b[i]]++; // 记录b[i]入度
// 因为topsort会在过程中执行--ind[j]而此图和入度的值后面还要继续用不能让topsort改坏了
// 复制出来一个临时的入度数组in[]
memcpy(in, ind, sizeof ind);
// 每输入一个关系表达式就topsort一次
int res = topsort();
// 拓扑序唯一
if (res == 3) {
printf("Sorted sequence determined after %d relations: ", i);
for (int j = 1; j <= dl; j++) printf("%c", d[j] + 'A');
puts(".");
flag = 0;
break;
} else if (res == 1) { // 有环
printf("Inconsistency found after %d relations.\n", i);
flag = 0;
break;
}
}
// 最终还是没有发现矛盾,也没有输出唯一序,说明条件还是不够啊,顺序无法确定
if (flag) puts("Sorted sequence cannot be determined.");
}
return 0;
}