首先对于所有的无向边,我们使用并查集将两边的点并起来 若一条边未合并之前,两端的点已经处于同一个集合了,那么说明必定存在可行的环(因为这两个点处于同一个并查集集合中,那么它们之间至少存在一条路径) 如果上一步没有判断出环,那么仅靠无向边是找不到环的 考虑到,处于同一个并查集集合中的点之间必定存在一条路径互达,因此将一个集合的点合并之后,原问题等价于在新生成的有向图中是否有环 我们知道,有向无环图必定存在拓扑序,因此只需使用拓扑排序判定即可 时间复杂度O(N+M1+M2)O(N + M1 + M2)O(N+M1+M2)
笨人搓码 hdu的栈溢出真是快让我炸了。。
1 /*Author :usedrose */ 2 /*Created Time :2015/7/31 18:35:37*/ 3 /*File Name :2.cpp*/ 4 #pragma comment(linker, "/STACK:102400000,102400000") 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <sstream> 9 #include <cstdlib> 10 #include <cstring> 11 #include <climits> 12 #include <vector> 13 #include <string> 14 #include <ctime> 15 #include <cmath> 16 #include <deque> 17 #include <queue> 18 #include <stack> 19 #include <set> 20 #include <map> 21 #define INF 0x3f3f3f3f 22 #define eps 1e-8 23 #define pi acos(-1.0) 24 #define MAXN 1000000 25 #define OK cout << "ok" << endl; 26 #define o(a) cout << #a << " = " << a << endl 27 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 28 using namespace std; 29 typedef long long LL; 30 31 int fa[MAXN]; 32 int n, m1, m2; 33 vector<int> G[MAXN]; 34 int vis[MAXN], ind[MAXN]; 35 36 int findset(int x) 37 { 38 return fa[x] = fa[x] == x ? x:findset(fa[x]); 39 } 40 41 bool merg(int a, int b) 42 { 43 int x = findset(a); 44 int y = findset(b); 45 if (x == y) return false; 46 fa[x] = y; 47 return true; 48 } 49 50 void init() 51 { 52 for (int i = 1;i <= n; ++ i) { 53 fa[i] = i; 54 ind[i] = 0; 55 G[i].clear(); 56 } 57 } 58 59 60 bool toposort() 61 { 62 queue<int> Q; 63 for (int i = 1;i <= n; ++ i) { 64 if (ind[i] == 0 && fa[i] == i) 65 Q.push(i); 66 } 67 while (!Q.empty()) { 68 int t = Q.front(); 69 Q.pop(); 70 for (int i = 0;i < G[t].size(); ++ i) { 71 int v = G[t][i]; 72 if (--ind[v] == 0) 73 Q.push(v); 74 } 75 } 76 for (int i = 1;i <= n; ++ i) 77 if (ind[i]) 78 return false; 79 return true; 80 } 81 82 int main() 83 { 84 //freopen("data.in","r",stdin); 85 //freopen("data.out","w",stdout); 86 int T; 87 scanf("%d", &T); 88 while (T--) { 89 scanf("%d%d%d", &n, &m1, &m2); 90 init(); 91 bool ans = true; 92 int x, y; 93 for (int i = 1;i <= m1; ++ i) { 94 scanf("%d%d", &x, &y); 95 ans &= merg(x, y); 96 } 97 98 for (int i = 1;i <= m2; ++ i) { 99 scanf("%d%d", &x, &y); 100 x = findset(x); 101 y = findset(y); 102 G[x].push_back(y); 103 ind[y]++; 104 } 105 if (ans == 0) { 106 puts("YES"); 107 continue; 108 } 109 110 ans = toposort(); 111 puts(ans? "NO" : "YES"); 112 } 113 return 0; 114 }
时间: 2024-10-10 15:47:55