POJ 2762 (弱连通)强连通+缩点+拓扑排序

题意:给出T个山洞,对于每个山洞,如果任意选择两点s,e,都满足s可以到达e或者e可以到达s,则输出Yes,否则输出No。

思路:如果两点不可达那么在拓扑排序时,该两点谁也不是谁的前驱和后继,那么在拓扑排序时定会出现至少两个度为0的点,这两个点分别是它们本身或它们的拓扑序列的前驱。如果在拓扑排序时发现有多于1个度为0的点,那么这些点必然不可达。由此推出该题为No的充分必要条件:缩点拓扑排序过程中出现至少两个度为0的点。

思路摘自:http://happylch21.blog.163.com/blog/static/1656397592011711261518/

(我还是刚知道弱连通这个东西。。)

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <iostream>
  5 
  6 #define N 1200
  7 #define M 12000
  8 
  9 using namespace std;
 10 
 11 int n,m,to[M],next[M],head[N],in[N],cnt,dfn[N],low[N],divg,t,p,stk[N],belong[N],tt;
 12 int next1[M],to1[M],head1[N],cnt1;
 13 bool fg[N],map[N][N];
 14 
 15 inline void add(int u,int v)
 16 {
 17     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
 18 }
 19 
 20 inline void add1(int u,int v)
 21 {
 22     to1[cnt1]=v; next1[cnt1]=head1[u]; head1[u]=cnt1++;
 23 }
 24 
 25 void read()
 26 {
 27     memset(head,-1,sizeof head);cnt=0;
 28     memset(dfn,0,sizeof dfn);
 29     memset(fg,0,sizeof fg);
 30     t=0; divg=0; p=0;
 31     scanf("%d%d",&n,&m);
 32     for(int i=1,a,b;i<=m;i++)
 33     {
 34         scanf("%d%d",&a,&b);
 35         add(a,b);
 36     }
 37 }
 38 
 39 void dfs(int u)
 40 {
 41     t++;
 42     dfn[u]=low[u]=t;
 43     stk[++p]=u; fg[u]=true;
 44     for(int i=head[u];~i;i=next[i])
 45     {
 46         if(!dfn[to[i]])
 47         {
 48             dfs(to[i]);
 49             low[u]=min(low[u],low[to[i]]);
 50         }
 51         else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]);
 52     }
 53     if(dfn[u]==low[u])
 54     {
 55         divg++;
 56         int tmp=-1;
 57         while(tmp!=u)
 58         {
 59             tmp=stk[p--];
 60             belong[tmp]=divg;
 61             fg[tmp]=false;
 62         }
 63     }
 64 }
 65 
 66 void rebuild()
 67 {
 68     memset(in,0,sizeof in);
 69     memset(map,0,sizeof map);
 70     memset(head1,-1,sizeof head1);cnt1=0;
 71     for(int i=1;i<=n;i++)
 72         for(int j=head[i];~j;j=next[j])
 73             if(belong[i]!=belong[to[j]]&&!map[belong[i]][belong[to[j]]])
 74             {
 75                 in[belong[to[j]]]++;
 76                 add1(belong[i],belong[to[j]]);
 77                 map[belong[i]][belong[to[j]]]=true;
 78             }
 79 }
 80 
 81 bool toposort()
 82 {
 83     int num=0,cur;
 84     for(int i=1;i<=divg;i++)
 85         if(!in[i]) cur=i,num++;
 86     if(num>1) return false;
 87     int tmp=divg;
 88     while(tmp--)
 89     {
 90         num=0;
 91         for(int i=head1[cur];~i;i=next1[i])
 92         {
 93             in[to1[i]]--;
 94             if(!in[to1[i]]) num++,cur=to1[i];
 95         }
 96         if(num>1) return false;
 97     }
 98     return true;
 99 }
100 
101 void go()
102 {
103     for(int i=1;i<=n;i++)
104         if(!dfn[i]) dfs(i);
105     if(divg==1)
106     {
107         puts("Yes");
108         return;
109     }
110     
111     
112     rebuild();
113     if(toposort()) puts("Yes");
114     else puts("No");
115 }
116 
117 int main()
118 {
119     scanf("%d",&tt);
120     while(tt--)
121     {
122         read();
123         go();
124     }
125     system("pause");
126     return 0;
127 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2710594.html