題目鏈接:
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 }