HDU 1269.迷宫城堡-Tarjan or 双向DFS

迷宫城堡

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 20476    Accepted Submission(s): 8917


Problem Description
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。
 
Input
输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。
 
Output
对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
 
Sample Input
3 3 1 2 2 3 3 1 3 3 1 2 2 3 3 2 0 0
 
Sample Output
Yes No
 
Author
Gardon
 
Source
 
 
 
代码1:Tarjan
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<stack>
 5 using namespace std;
 6 const int N=1e5+10;
 7 stack<int>sta;
 8 vector<int>gra[N];
 9 int dfn[N],low[N],InStack[N];
10 vector<int>Component[N];
11 int InComponent[N];
12 int index,ComponentNumber;
13 int n,m;
14 void init(){
15     memset(dfn,0,sizeof(dfn));
16     memset(low,0,sizeof(low));
17     memset(InStack,0,sizeof(InStack));
18     index=ComponentNumber=0;
19     for(int i=1;i<=n;i++){
20         gra[i].clear();
21         Component[i].clear();
22     }
23     while(!sta.empty())
24         sta.pop();
25 }
26 void tarjan(int u){
27     InStack[u]=2;
28     low[u]=dfn[u]=++index;
29     sta.push(u);
30     for(int i=0;i<gra[u].size();++i){
31         int t=gra[u][i];
32         if(dfn[t]==0){
33             tarjan(t);
34             low[u]=min(low[u],low[t]);
35         }
36         else if(InStack[t]==2){
37             low[u]=min(low[u],dfn[t]);
38         }
39     }
40     if(low[u]==dfn[u]){
41         ++ComponentNumber;
42         while(!sta.empty()){
43             int j=sta.top();
44             sta.pop();
45             InStack[j]=1;
46             Component[ComponentNumber].push_back(j);
47             InComponent[j]=ComponentNumber;
48             if(j==u)break;
49         }
50     }
51 }
52 void input(){
53     for(int i=1;i<=m;i++){
54         int a,b;
55         scanf("%d%d",&a,&b);
56         gra[a].push_back(b);
57     }
58 }
59 void solve(){
60     for(int i=1;i<=n;i++)
61         if(!dfn[i])tarjan(i);
62         if(ComponentNumber>1)puts("No");
63         else puts("Yes");
64 }
65 int main(){
66     while(scanf("%d%d",&n,&m),n+m){
67         init();
68         input();
69         solve();
70     }
71     return 0;
72 }

代码2:双向DFS

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn = 10000 + 5;
 9 vector<int> node[maxn];
10 vector<int> reverse_node[maxn];
11 vector<int> reverse_post;
12 int marked[maxn];
13 int N,M;
14 
15 void reverse_dfs(int v){
16     marked[v] = 1;
17     for(int w=0;w<reverse_node[v].size();w++){
18         int to = reverse_node[v][w];
19         if(!marked[to]){
20                 //cout<<"dfs="<<to<<endl;
21                 reverse_dfs(to);
22         }
23     }
24     //cout<<"post in="<<v<<endl;
25     reverse_post.push_back(v);
26 }
27 
28 void get_reverse(){
29     reverse_post.clear();
30     for(int v=1;v<=N;v++){
31         if(!marked[v]){
32             //cout<<"start="<<v<<endl;
33             reverse_dfs(v);
34         }
35     }
36 }
37 
38 void dfs(int v){
39     marked[v] = 1;
40     for(int w=0;w<node[v].size();w++){
41         int to = node[v][w];
42         if(!marked[to])dfs(to);
43     }
44 }
45 
46 int main(){
47     while(cin>>N>>M){
48         if(N+M==0) break;
49         for(int i=1;i<=N;i++){
50             node[i].clear();
51             reverse_node[i].clear();
52             marked[i]=0;
53         }
54         for(int i=0;i<M;i++){
55             int a,b;
56             scanf("%d%d",&a,&b);
57             node[a].push_back(b);
58             reverse_node[b].push_back(a);
59         }
60         get_reverse();
61         for(int i=1;i<=N;i++){
62             marked[i] = 0;
63         }
64         int num=0;
65         for(int i=reverse_post.size()-1;i>=0;i--){
66             int to = reverse_post[i];
67             if(!marked[to]){
68                 //cout<<"again dfs="<<to<<endl;
69                 if(num==1){
70                     num=2;
71                     break;
72                 }
73                 dfs(to);
74                 num++;
75             }
76         }
77         printf("%s
",num==1?"Yes":"No");
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/ZERO-/p/9114434.html