迷宫城堡
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
1 2
2 3
3 1
3 3
1 2
2 3
3 2
0 0
Sample Output
Yes
No
No
Author
Gardon
Source
代码1:Tarjan
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
const int N=1e5+;
stack<int>sta;
vector<int>gra[N];
int dfn[N],low[N],InStack[N];
vector<int>Component[N];
int InComponent[N];
int index,ComponentNumber;
int n,m;
void init(){
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(InStack,,sizeof(InStack));
index=ComponentNumber=;
for(int i=;i<=n;i++){
gra[i].clear();
Component[i].clear();
}
while(!sta.empty())
sta.pop();
}
void tarjan(int u){
InStack[u]=;
low[u]=dfn[u]=++index;
sta.push(u);
for(int i=;i<gra[u].size();++i){
int t=gra[u][i];
if(dfn[t]==){
tarjan(t);
low[u]=min(low[u],low[t]);
}
else if(InStack[t]==){
low[u]=min(low[u],dfn[t]);
}
}
if(low[u]==dfn[u]){
++ComponentNumber;
while(!sta.empty()){
int j=sta.top();
sta.pop();
InStack[j]=;
Component[ComponentNumber].push_back(j);
InComponent[j]=ComponentNumber;
if(j==u)break;
}
}
}
void input(){
for(int i=;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
gra[a].push_back(b);
}
}
void solve(){
for(int i=;i<=n;i++)
if(!dfn[i])tarjan(i);
if(ComponentNumber>)puts("No");
else puts("Yes");
}
int main(){
while(scanf("%d%d",&n,&m),n+m){
init();
input();
solve();
}
return ;
}
代码2:双向DFS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = + ;
vector<int> node[maxn];
vector<int> reverse_node[maxn];
vector<int> reverse_post;
int marked[maxn];
int N,M; void reverse_dfs(int v){
marked[v] = ;
for(int w=;w<reverse_node[v].size();w++){
int to = reverse_node[v][w];
if(!marked[to]){
//cout<<"dfs="<<to<<endl;
reverse_dfs(to);
}
}
//cout<<"post in="<<v<<endl;
reverse_post.push_back(v);
} void get_reverse(){
reverse_post.clear();
for(int v=;v<=N;v++){
if(!marked[v]){
//cout<<"start="<<v<<endl;
reverse_dfs(v);
}
}
} void dfs(int v){
marked[v] = ;
for(int w=;w<node[v].size();w++){
int to = node[v][w];
if(!marked[to])dfs(to);
}
} int main(){
while(cin>>N>>M){
if(N+M==) break;
for(int i=;i<=N;i++){
node[i].clear();
reverse_node[i].clear();
marked[i]=;
}
for(int i=;i<M;i++){
int a,b;
scanf("%d%d",&a,&b);
node[a].push_back(b);
reverse_node[b].push_back(a);
}
get_reverse();
for(int i=;i<=N;i++){
marked[i] = ;
}
int num=;
for(int i=reverse_post.size()-;i>=;i--){
int to = reverse_post[i];
if(!marked[to]){
//cout<<"again dfs="<<to<<endl;
if(num==){
num=;
break;
}
dfs(to);
num++;
}
}
printf("%s\n",num==?"Yes":"No");
}
return ;
}