poj2762 强连通+拓扑序

题意:有 n 个房间,不同房间之间有单向通道,问是否任意两个房间 A 、B 都可以从 A 到 B 或从 B 到 A(有一条有就可以)。

在这题中,如果一些点是在同一个强连通分量中,那么这些点肯定能够相互到达,并且如果其他的点到达这里的任意一点,也就可以到达强连通分量中的所有点,所以首先需要对这题进行缩点。缩点之后图中就不存在环了,这时需要所有点间都至少有一条路,所以其实剩下了一条长链,并且是单向的,如果有双向的边就会被缩点,如果是数型图的话那么一个节点的多个子树就不能互相到达,所以一定是一条单向的长链,因此只要拓扑序判断就行,也可以对于这个图判段是否只有一点入度为1,一点出度为1,剩余点出入度都为1就行。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stack>
  4 #include<queue>
  5 using namespace std;
  6 
  7 const int maxn=1005;
  8 const int maxm=6005;
  9 
 10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
 11 int n,t,scccnt;
 12 int id[maxn],stx[maxn],low[maxn],scc[maxn];
 13 stack<int>S;
 14 
 15 void init(){
 16     memset(head,-1,sizeof(head));
 17     size[0]=size[1]=0;
 18     memset(id,0,sizeof(head));
 19 }
 20 
 21 void add(int a,int b,int c=0){
 22     point[c][size[c]]=b;
 23     nxt[c][size[c]]=head[c][a];
 24     head[c][a]=size[c]++;
 25     if(c)id[b]++;
 26 }
 27 
 28 void dfs(int s){
 29     stx[s]=low[s]=++t;
 30     S.push(s);
 31     for(int i=head[0][s];~i;i=nxt[0][i]){
 32         int j=point[0][i];
 33         if(!stx[j]){
 34             dfs(j);
 35             low[s]=min(low[s],low[j]);
 36         }
 37         else if(!scc[j]){
 38             low[s]=min(low[s],stx[j]);
 39         }
 40     }
 41     if(low[s]==stx[s]){
 42         scccnt++;
 43         while(1){
 44             int u=S.top();S.pop();
 45             scc[u]=scccnt;
 46             if(s==u)break;
 47         }
 48     }
 49 }
 50 
 51 void setscc(){
 52     memset(stx,0,sizeof(stx));
 53     memset(scc,0,sizeof(scc));
 54     t=0;
 55     scccnt=0;
 56     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
 57     for(int i=1;i<=n;++i){
 58         for(int j=head[0][i];~j;j=nxt[0][j]){
 59             int k=point[0][j];
 60             if(scc[i]!=scc[k]){
 61                 add(scc[i],scc[k],1);
 62             }
 63         }
 64     }
 65 }
 66 
 67 bool topo(){
 68     queue<int>q;
 69     int cnt=0;
 70     for(int i=1;i<=scccnt;++i)if(!id[i])q.push(i);
 71     while(!q.empty()){
 72         int u=q.front();
 73         q.pop();
 74         if(!q.empty())return 0;
 75         cnt++;
 76         for(int i=head[1][u];~i;i=nxt[1][i]){
 77             int j=point[1][i];
 78             id[j]--;
 79             if(!id[j])q.push(j);
 80         }
 81     }
 82     if(cnt==scccnt)return 1;
 83     return 0;
 84 }
 85 
 86 int main(){
 87     int T;
 88     scanf("%d",&T);
 89     while(T--){
 90         int m;
 91         scanf("%d%d",&n,&m);
 92         init();
 93         while(m--){
 94             int a,b;
 95             scanf("%d%d",&a,&b);
 96             add(a,b);
 97         }
 98         setscc();
 99         if(topo())printf("Yes
");
100         else printf("No
");
101     }
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/4797734.html