题意:给出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 }