zoukankan      html  css  js  c++  java
  • 并查集+拓扑排序 赛码 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 }
    编译人生,运行世界!
  • 相关阅读:
    ioremap函数
    kmalloc、kzalloc和vmalloc
    C语言 snprintf函数
    C语言 memset函数
    消息队列
    mount -a
    linux系统查看服务状态和启动停止服务
    Java中创建对象的内存图
    Java中数组在内存中的图解
    socket编程(Java实现)
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4475659.html
Copyright © 2011-2022 走看看