POJ1094——拓扑排序和它的唯一性
比较模板的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 }