比較模板的topological-sort題,關鍵在於每個元素都嚴格存在唯一的大小關系,而一般的拓撲排序只給出一個可能解,這就需要每趟排序的過程中監視它是不是總堅持一條唯一的路徑。
算法導論里面的拓撲排序運用的是DFS the DAG,記錄每個頂點的進入時間和離開時間,根據其先后插入單鏈表的做法。而我認為一種方法是更直觀的,就是維護一個入度為0的頂點集合(我用的隊列其實沒差),每次對其中一個加入結果序列——同時刪除它的所有出邊——更新其他點的入度的做法,在我的算法數據結構實現模板里有正確實現https://github.com/jily16/ACMCodes(打廣告
在判斷拓撲排序結果唯一性時這種方法也表現出了一個優勢,每次訪問0入度集合時查看大小,當元素多於1的時候可行的選擇就出現了分歧——即可判定此DAG的拓撲排序不唯一(當然本題的信息在不斷更新,所以不能立刻判死)。
AC代碼:
1 #include <vector> 2 #include <iostream> 3 #include <queue> 4 using namespace std; 5 //POJ1094 6 int const INF = 0x3f3f3f3f; 7 //返回空數組說明暫時不行 8 //cyclic說明矛盾 9 vector<int> ts(vector<vector<int> > const &g, bool &cyclic) 10 { 11 int n = g.size(); 12 vector<int> d(n); 13 for (int i = 0; i < n; ++i) 14 { 15 for (int j = 0; j < n; ++j) 16 { 17 if (g[i][j] < INF) 18 { 19 ++d[j]; 20 } 21 } 22 } 23 queue<int> q; 24 for (int i = 0; i < n; ++i) if (d[i] == 0) q.push(i); 25 int d0; 26 int tot = 0; 27 bool not_unique = false; 28 vector<int> ans; 29 while (!q.empty()) 30 { 31 if (q.size() > 1) 32 { 33 not_unique = true; //解不唯一 34 } 35 d0 = q.front(); 36 q.pop(); 37 ans.push_back(d0); 38 ++tot; 39 for (int i = 0; i < n; ++i) 40 { 41 if (d[i] != 0 && g[d0][i] < INF) 42 { 43 --d[i]; 44 if (d[i] == 0) 45 { 46 q.push(i); 47 } 48 } 49 } 50 } 51 if (tot != n) cyclic = true; 52 if (not_unique) return vector<int>(); 53 else return ans; 54 } 55 int main() 56 { 57 int n, m; 58 while (cin >> n >> m && n && m) 59 { 60 bool done = false; 61 vector<vector<int> > g; 62 char alp1, alp2; 63 char lessthan; 64 int num1, num2; 65 for (int i = 0; i < m; ++i) 66 { 67 cin >> alp1 >> lessthan >> alp2; 68 if (done) continue; 69 num1 = alp1 - 'A'; 70 num2 = alp2 - 'A'; 71 int bignum = max(num1, num2); 72 //extend the graph 73 if (g.size() < bignum + 1) 74 { 75 int ori_size = g.size(); 76 for (int i = 0; i < ori_size; ++i) 77 { 78 for (int j = 0; j < bignum + 1 - ori_size; ++j) 79 { 80 g[i].push_back(INF); 81 } 82 } 83 for (int i = 0; i < bignum + 1 - ori_size; ++i) 84 { 85 g.push_back(vector<int>(bignum + 1, INF)); 86 } 87 } 88 g[num1][num2] = 1; 89 //judge from here 90 bool cycle = false; 91 if (g.size() < n) 92 { 93 ts(g, cycle); 94 if (cycle) 95 { 96 cout << "Inconsistency found after " << i + 1 << " relations.\n"; 97 done = true; 98 } 99 else 100 { 101 if (i == m - 1) 102 { 103 cout << "Sorted sequence cannot be determined.\n"; 104 done = true; 105 } 106 } 107 } 108 else 109 { 110 vector<int> ans = ts(g, cycle); 111 if (cycle) 112 { 113 cout << "Inconsistency found after " << i + 1 << " relations.\n"; 114 done = true; 115 } 116 else 117 { 118 if (ans.size() != 0) 119 { 120 cout << "Sorted sequence determined after " << i + 1 << " relations: "; 121 for (int i = 0; i < n; ++i) cout << (char)(ans[i] + 'A'); 122 cout << ".\n"; 123 done = true; 124 } 125 else 126 { 127 if (i < m - 1) continue; 128 else 129 { 130 cout << "Sorted sequence cannot be determined.\n"; 131 done = true; 132 } 133 } 134 } 135 } 136 } 137 } 138 return 0; 139 }
