• 图的单向连通


    poj 2762

      题意:任给一个图,问你对于任意的两个点x,y之间是否存在从x到y或从y到x的路径?

      分析:这显然是要求图是否为单向连通图?我们可以对强连通分量进行缩点,缩点后的图一定是一个有向无环图; 现在,问题等价于给你一个有向无环图,问你它是否为单向连通图。这样,我们就可以对有向无环图进行拓扑排序,当且仅当得到的拓扑序列中任意相邻两点间边连通,即topo[i]--topo[i+1]之间存在边时,有向无环图是单向连通图。

      

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<algorithm>
      5 #define _Clr(x, y) memset(x, y, sizeof(x))
      6 #define INF 0x3f3f3f3f
      7 #define N 1010
      8 using namespace std;
      9 
     10 struct Node
     11 {
     12     int to, next;
     13 }edge[N*6];
     14 int head[N], tot;
     15 int dfn[N], low[N];
     16 int bleg[N], Sta[N];
     17 bool instack[N];
     18 int cnt, top, ght, n;
     19 
     20 void Init()
     21 {
     22     cnt=tot=ght=top=0;
     23     _Clr(head, -1);
     24     _Clr(dfn, 0);
     25     _Clr(instack, 0);
     26 }
     27 
     28 void Add_edge(int a, int b)
     29 {
     30     edge[tot].to = b;
     31     edge[tot].next = head[a];
     32     head[a] = tot++;
     33 }
     34 
     35 void dfs(int u)
     36 {
     37     dfn[u]=low[u]=++cnt;
     38     Sta[top++] = u;
     39     instack[u] = true;
     40     for(int i=head[u]; i!=-1; i=edge[i].next)
     41     {
     42         int v = edge[i].to;
     43         if(!dfn[v])
     44         {
     45             dfs(v);
     46             low[u] = min(low[u], low[v]);
     47         }
     48         else if(instack[v]) low[u] = min(low[u], dfn[v]);
     49     }
     50     if(low[u]==dfn[u])
     51     {
     52         ght++;
     53     //    printf("Num: %d
    ",ght);
     54         int v;
     55         do
     56         {
     57             v = Sta[--top];
     58       //      printf("%d ",  v);
     59             instack[v] = false;
     60             bleg[v] = ght;
     61         }while(u!=v);
     62     //    puts("");
     63     }
     64 }
     65 
     66 int inde[N], mat[N][N];
     67 void Tarjan()
     68 {
     69     for(int i=1; i<=n; i++)
     70         if(!dfn[i]) dfs(i);
     71 
     72     _Clr(inde, 0);
     73     _Clr(mat, 0);
     74     // 缩点建立新的有向无环图并且求每个点的入度
     75     for(int u=1; u<=n; u++)
     76     for(int i=head[u]; i!=-1; i=edge[i].next)
     77     {
     78         int v = edge[i].to;
     79         if(bleg[v] != bleg[u])
     80         {
     81             inde[bleg[v]]++;
     82             mat[bleg[u]][bleg[v]] = 1;
     83         }
     84     }
     85 }
     86 
     87 int topo[N], k=0;
     88 void TopSort()
     89 {
     90     queue<int> Q;
     91     for(int i=1; i<=ght; i++)
     92         if(inde[i]==0) Q.push(i);
     93   //  printf("TopSort: 
    ");
     94     k=0;
     95     while(!Q.empty())
     96     {
     97         int u = Q.front(); Q.pop();
     98     //    printf("%d ", u);
     99         topo[++k] = u;
    100         for(int i=1; i<=ght; i++)
    101         {
    102             if(!mat[u][i]) continue;
    103             inde[i]--;
    104             if(inde[i]==0) Q.push(i);
    105         }
    106     }
    107    // puts("");
    108 }
    109 
    110 void Solved()
    111 {
    112     bool tag = true;
    113   //  printf("k=%d
    ", k);
    114     for(int i=1; i<k; i++)
    115         if(!mat[topo[i]][topo[i+1]])    //若拓扑序列存在两个相邻的点之间不连通则非单向连通图
    116         {
    117             tag = false;
    118             break;
    119         }
    120     puts(tag ? "Yes" : "No");
    121 }
    122 
    123 int main()
    124 {
    125     int T, m, a, b;
    126     scanf("%d", &T);
    127     while(T--)
    128     {
    129         Init();
    130         scanf("%d%d", &n, &m);
    131         while(m--)
    132         {
    133             scanf("%d%d",&a, &b);
    134             Add_edge(a, b);
    135         }
    136         Tarjan();
    137         TopSort();
    138         Solved();
    139     }
    140     return 0;
    141 }
    View Code
  • 相关阅读:
    sqlserver判断字段是否存在,表是否存在
    sqlserver数据库数据字典生成器
    C#断点续传下载文件
    c# 泛型new T
    html显示xml内容
    程序设计语言诞生——程序设计语言的发展历史
    atan2(x,y) pow(x,y)
    name phone email 正则表达式
    第八周
    第六周
  • 原文地址:https://www.cnblogs.com/khan724/p/4374079.html
Copyright © 2020-2023  润新知