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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?