POJ- 1094 Sorting It All Out---拓扑排序是否唯一的判断
题目链接:
https://vjudge.net/problem/POJ-1094
题目大意:
该题题意明确,就是给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列。是典型的拓扑排序,但输出格式上确有三种形式:
1.该字母序列有序,并依次输出;
2.该序列不能判断是否有序(序列不唯一);
3.该序列字母次序之间有矛盾,即有环存在。
思路:
这里应该用Kahn算法拓扑排序
每加入一条边需要进行一次拓扑排序,如果拓扑排序发现有环,或者排序唯一那么就可以直接输出结果,如果所有的边输入完成还不是上述两种情况,那就输出不能判断。
这里的重点在于如何判断拓扑排序的唯一性,这里运用了Kahn算法的思想。
Kahn算法:
1.找到入度为0的顶点加入栈中,然后提出栈顶元素,成为拓扑排序的一部分
2.除去与之相邻所有边并减少其度数,再次加入入度数为0的点循环往复,如果某一次栈已经空了而且没有入读为0的点,那就是存在有向环。
判断唯一性:
那就得每次找到入度为0的顶点个数只能是1个,是0个说明存在环,多个说明拓扑排序不唯一。
由于每次只能有一个0度顶点,所以可以循环n次,依次找出拓扑排序中的每一位
需要注意的是,如果有一次找出了多个0度顶点,不能直接返回无序,只能暂时标记,因为可能之后的循环中存在环。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<set> 10 #include<sstream> 11 #include<functional> 12 using namespace std; 13 typedef long long ll; 14 const int maxn = 100 + 10; 15 const int INF = 1e9 + 7; 16 int T, n, m, cases; 17 vector<int>Map[maxn]; 18 int Count[maxn]; 19 int ans[maxn]; 20 int topo() 21 { 22 int cnt[maxn]; 23 memcpy(cnt, Count, sizeof(Count)); 24 int flag = 1; 25 for(int i = 0; i < n; i++)//为判断顺序是否唯一,有序的顺序拓扑排序需要n次循环 26 { 27 int tot = 0;//度数为0的顶点的个数,超过一个说明拓扑排序一定不是唯一,可能不能确定,可能有环 28 int u;//记录度数为0的点 29 for(int j = 0; j < n; j++)if(cnt[j] == 0){tot++, u = j;} 30 if(tot == 0)return 0;//有环 31 if(tot > 1)flag = -1;//一定不唯一,但是不能立马退出,因为之后有可能是有环 32 ans[i] = u;//记录拓扑排序顺序 33 cnt[u] = -1;//已经排好,设成负数 34 for(int j = 0; j < Map[u].size(); j++) 35 { 36 int v = Map[u][j]; 37 cnt[v]--; 38 } 39 } 40 return flag; 41 } 42 int main() 43 { 44 while(cin >> n >> m) 45 { 46 if(!n && !m)break; 47 string s; 48 int flag = 0; 49 for(int i = 0; i <= n; i++)Map[i].clear(); 50 memset(Count, 0, sizeof(Count)); 51 for(int i = 1; i <= m; i++) 52 { 53 cin >> s; 54 int u = s[0] - 'A'; 55 int v = s[2] - 'A'; 56 Map[u].push_back(v); 57 Count[v]++;//入度 58 if(flag)continue;//如果已经判断出有序或者有环,就不做处理 59 int t = topo(); 60 //cout<<t<<endl; 61 if(t == 0)//有环 62 { 63 printf("Inconsistency found after %d relations.\n",i); 64 flag = 1; 65 } 66 if(t == 1)//有序 67 { 68 printf("Sorted sequence determined after %d relations: ",i); 69 for(int i = 0; i < n; i++)printf("%c", ans[i] + 'A'); 70 printf(".\n"); 71 flag = 1; 72 } 73 } 74 if(!flag)printf("Sorted sequence cannot be determined.\n"); 75 } 76 return 0; 77 }
越努力,越幸运