图的单向连通

 

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\n",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: \n");
 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\n", 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

 

转载于:https://www.cnblogs.com/khan724/p/4374079.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值