并查集+拓扑排序 赛码 1009 Exploration

 

题目传送门

 1 /*  2  题意:无向图和有向图的混合图判环;  3  4  官方题解:首先对于所有的无向边,我们使用并查集将两边的点并起来,若一条边未合并之前,  5  两端的点已经处于同一个集合了,那么说明必定存在可行的环(因为这两个点处于同一个并查集集合中,那么它们之间至少存在一条路径)  6  如果上一步没有判断出环,那么仅靠无向边是找不到环的  7  考虑到,处于同一个并查集集合中的点之间必定存在一条路径互达,因此将一个集合的点合并之后,  8  原问题等价于在新生成的有向图中是否有环  9  我们知道,有向无环图必定存在拓扑序,因此只需使用拓扑排序判定即可  10  时间复杂度O(N+M1+M2)  11  12  并查集+拓扑排序:并查集来判断无向图,拓扑排序判断有向图  13  14  另外:用读入外挂时间比scanf ()多,不清楚...  15  Accepted 5222 5007MS 45124K 2158 B G++ BH //scanf ()  16  Accepted 5222 7581MS 45116K 2158 B G++ BH //read ()  17 */  18 #include <cstdio>  19 #include <cmath>  20 #include <cstring>  21 #include <string>  22 #include <iostream>  23 #include <algorithm>  24 #include <queue>  25 #include <vector>  26 #pragma comment(linker, "/STACK:102400000,102400000")  27 using namespace std;  28  29 const int MAXN = 1e6 + 10;  30 const int INF = 0x3f3f3f3f;  31 int ans[MAXN], in[MAXN];  32 int rt[MAXN];  33 vector<int> G[MAXN];  34 int n, m1, m2;  35  36 inline int read(void)  37 {  38 int x = 0, f = 1; char ch = getchar ();  39 while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar ();}  40 while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar ();}  41 return x * f;  42 }  43  44 bool TopoSort(void)  45 {  46 memset (in, 0, sizeof (in));  47 for (int i=1; i<=n; ++i)  48 for (int j=0; j<G[i].size (); ++j) in[G[i][j]]++;  49  50 queue<int> Q; int cnt = 0;  51 for (int i=1; i<=n; ++i) {if (!in[i]) Q.push (i);}  52  53 while (!Q.empty ())  54  {  55 int u = Q.front (); Q.pop ();  56 ans[++cnt] = u;  57 for (int j=0; j<G[u].size (); ++j)  58  {  59 int v = G[u][j];  60 in[v]--;  61 if (!in[v]) Q.push (v);  62  }  63  }  64  65 if (cnt == n) return false;  66 else return true;  67 }  68  69 int Find(int x)  70 {  71 return (rt[x] == x) ? rt[x] : rt[x] = Find (rt[x]);  72 }  73  74 void Union(int x, int y)  75 {  76 x = Find (x); y = Find (y);  77 if (x < y) rt[x] = y;  78 else rt[y] = x;  79 }  80  81 bool same(int x, int y)  82 {  83 return (Find (x) == Find (y)) ? true : false;  84 }  85  86 int main(void) //赛码 1009 Exploration  87 {  88 //freopen ("I.in", "r", stdin);  89  90 int t;  91 scanf ("%d", &t);  92 while (t--)  93  {  94 scanf ("%d%d%d", &n, &m1, &m2);  95  96 for (int i=1; i<=n; ++i) rt[i] = i;  97 for (int i=1; i<=n; ++i) G[i].clear ();  98  99 bool ok = false; int u, v; 100 for (int i=1; i<=m1; ++i) 101  { 102 scanf ("%d%d", &u, &v); 103 //u = read (); v = read (); 104 //G[u].push_back (v); 105 if (same (u, v) == true) ok = true; 106 else Union (u, v); 107  } 108 for (int i=1; i<=m2; ++i) 109  { 110 int u, v; 111 scanf ("%d%d", &u, &v); 112 //u = read (); v = read (); 113 if (same (u, v) == true) ok = true; 114 if (ok) continue; 115  G[u].push_back (v); 116  } 117 118 if (ok) {puts ("YES"); continue;} 119 if (TopoSort () == true) puts ("YES"); 120 else puts ("NO"); 121  } 122 123 return 0; 124 }

 

你可能感兴趣的:(exp)