并查集+拓扑排序 赛码 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 }

 

posted @ 2015-05-04 10:59  Running_Time  阅读(177)  评论(0编辑  收藏  举报