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. 

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
");
91         else printf("No
");
92     }
93     return 0;
94 }

思路:首先建一个有向图,进行Tarjan算法,进行缩点,缩完点之后,再建一张有向图(这张图只能成一条链),对其进行检验,入度为0的店只能有一个或没有。。

原文地址:https://www.cnblogs.com/suishiguang/p/6238775.html