POJ 2762 Going from u to v or from v to u? Tarjan算法 学习例题
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 17104 | Accepted: 4594 |
Description
In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
Input
The first line contains a single integer T, the number of test cases. And followed T cases.
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
Output
The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.
Sample Input
1
3 3
1 2
2 3
3 1
Sample Output
Yes
Source
POJ Monthly--2006.02.26,zgl & twb
题目大意:n个山洞,对于每两个山洞s,e,都满足s可以到达e或者e可以到达s,则输出Yes,否则输出No。(s到e或者e到s满足一个就可以)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<stack> 5 #define maxm 6010 6 #define maxn 1010 7 using namespace std; 8 int T,n,m; 9 struct edge{ 10 int u,v,next; 11 }e[maxm],ee[maxm]; 12 int head[maxn],js,headd[maxn],jss; 13 bool exist[maxn]; 14 int visx,cur;// cur--缩出的点的数量 15 int dfn[maxn],low[maxn],belong[maxn]; 16 int rudu[maxn],chudu[maxn]; 17 stack<int>st; 18 void init(){ 19 memset(rudu,0,sizeof(rudu));memset(chudu,0,sizeof(chudu)); 20 memset(head,0,sizeof(head));memset(headd,0,sizeof(headd)); 21 jss=js=visx=cur=0; 22 memset(exist,false,sizeof(exist)); 23 while(!st.empty())st.pop(); 24 memset(dfn,-1,sizeof(dfn));memset(low,-1,sizeof(low)); 25 memset(belong,0,sizeof(belong)); 26 } 27 void add_edge1(int u,int v){ 28 e[++js].u=u;e[js].v=v; 29 e[js].next=head[u];head[u]=js; 30 } 31 void tarjan(int u){ 32 dfn[u]=low[u]=++visx; 33 exist[u]=true; 34 st.push(u); 35 for(int i=head[u];i;i=e[i].next){ 36 int v=e[i].v; 37 if(dfn[v]==-1){ 38 tarjan(v); 39 if(low[v]<low[u]) low[u]=low[v]; 40 } 41 else if(exist[v]&&low[u]>dfn[v]) low[u]=dfn[v]; 42 } 43 int j; 44 if(low[u]==dfn[u]){ 45 ++cur; 46 do{ 47 j=st.top();st.pop();exist[j]=false; 48 belong[j]=cur; 49 }while(j!=u); 50 } 51 } 52 void add_edge2(int u,int v){ 53 ee[++jss].u=u;ee[jss].v=v; 54 ee[jss].next=headd[u];headd[u]=jss; 55 } 56 bool topo() 57 { 58 int tp=0,maxt=0; 59 for(int i=1;i<=cur;i++) 60 { 61 if(rudu[i]==0){ 62 tp++; 63 } 64 if(chudu[i]>maxt)maxt=chudu[i]; 65 } 66 if(tp>1)return 0;// 入读等于0的缩点只能有一个 否则.. 67 if(maxt>1)return 0; 68 return 1; 69 } 70 int main() 71 { 72 scanf("%d",&T); 73 while(T--){ 74 scanf("%d%d",&n,&m); 75 init(); 76 int u,v; 77 for(int i=0;i<m;i++){ 78 scanf("%d%d",&u,&v);add_edge1(u,v); 79 } 80 for(int i=1;i<=n;i++){// 求强连通分量 81 if(dfn[i]==-1) tarjan(i); 82 } 83 for(int i=1;i<=js;i++){ 84 int u=e[i].u,v=e[i].v; 85 if(belong[u]!=belong[v]){ 86 add_edge2(belong[u],belong[v]); 87 rudu[belong[v]]++;chudu[belong[u]]++; 88 } 89 } 90 if(topo()==1) printf("Yes\n"); 91 else printf("No\n"); 92 } 93 return 0; 94 }
思路:首先建一个有向图,进行Tarjan算法,进行缩点,缩完点之后,再建一张有向图(这张图只能成一条链),对其进行检验,入度为0的店只能有一个或没有。。