常见的判断图中有无闭环的方式
最近做了一道ABC的D搞判断闭环搞了好久。。。其实会的方法挺多的但是做那个题的前一天睡眠严重不足导致脑子浑浊不清,索性来写个blog总结一下吧,顺便每种方法我尽量放上题目来更好的加深回忆。
1.并查集O(logn)
首先最简便的方法我觉得是首选并查集的,对于无向图和有向图都是满足的。主要思想就是如果在合并两个集合的时候发现此时合并的两个点如果已经在一个集合里了的话那么其实就形成了一个环。
例题:https://atcoder.jp/contests/abc285/tasks/abc285_d
这个题是一个有向图,并且可以用一个哈希表直接存,用并查集的时候千万要注意并查集的初始化问题。
#include <bits/stdc++.h> using namespace std; #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); const string YES = "YES"; const string NO = "NO"; int n; map<string, string> p; string find(string x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int32_t main() { gogo; bool ok = true; int n; cin >> n; for (int i = 0;i < n;i ++) { string x, y; cin >> x >> y; if (!p.count(x)) p[x] = x; if (!p.count(y)) p[y] = y; string a = find(x), b = find(y); if (a == b) ok = false; else p[a] = b; } cout << (ok ? "Yes" : "No") << '\n'; return 0; }
2.拓扑排序O(n+m)
首先拓扑排序的原理就是不断将当前所有入度为0的点push到队列里,然后全部删去,最终形成一个DAG(有向无环图),一个拓扑图也可以粗略抽象成分步做某一件事情,那么如果图中存在一个环的话那么这个环上的所有点永远都是入度为1的,也就是说这些点是永远不会被push到队列里的,那么只需要最一个图跑一遍拓扑序,然后看看是不是n个点都入队了可了。
例题:
拓扑排序代码:
1 //O(n + m) 2 int q[N], d[N], n, m; 3 vector<int> edge[N]; 4 5 bool TopoSort() { 6 int front = 1, rear = 0; 7 for (int i = 1;i <= n;i ++) 8 if (!d[i]) 9 q[++rear] = i; 10 while (front <= rear) { 11 int x = q[front]; 12 ++ front; 13 for (auto y : edge[x]) 14 if (--d[y] == 0) 15 q[++rear] = y; 16 } 17 if (rear == n) return 1; 18 else return 0; 19 } 20 21 int main() { 22 cin >> n >> m; 23 for (int i = 1;i <= m;i ++) { 24 int x, y; 25 cin >> x >> y; 26 edge[x].push_back(y); 27 d[y] ++; 28 } 29 30 if (TopoSort()) { 31 for (int i = 1;i <= n;i ++) { 32 cout << q[i] << ' '; 33 } 34 cout << endl; 35 } 36 else 37 cout << -1 << endl; 38 39 }

浙公网安备 33010602011771号