题目
描述
为了训练小希的方向感,Gardon建立了一座大城堡,里面有
N
N
N个房间和
M
M
M条通道,每个通道都是单向的,就是说若称某通道连通了
A
A
A房间和
B
B
B房间,只说明可以通过这个通道由
A
A
A房间到达
B
B
B房间,但并不说明通过它可以由
B
B
B房间到达
A
A
A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的
i
i
i和
j
j
j,至少存在一条路径可以从房间
i
i
i到房间
j
j
j,也存在一条路径可以从房间
j
j
j到房间
i
i
i。
输入
输入包含多组数据,输入的第一行有两个数:
N
N
N和
M
M
M,接下来的
M
M
M行每行有两个数
a
a
a和
b
b
b,表示了一条通道可以从
A
A
A房间来到
B
B
B房间。文件最后以两个0结束。
输出
对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
样例输入
3 3
1 2
2 3
3 1
3 3
1 2
2 3
3 2
0 0
样例输出
Yes
No
范围
N
≤
10000
,
M
≤
100000
N\leq 10000,M\leq100000
N≤10000,M≤100000
思路
其实就是看整个图的强连通分量是否为1就行了
代码
Kosaraju
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
#define M 10005
vector<int>G[M];
vector<int>G_t[M];
int n, m, u, v, ds, ans;
int time[M];
bool vis[M], flag;
inline void dfs(int x){
vis[x] = 1;
int siz = G[x].size();
for(int i = 0; i < siz; i ++){
int son = G[x][i];
if( !vis[son] )
dfs(son);
}
time[++ds] = x;
}
inline void redfs(int x){
vis[x] = 1;
int siz = G_t[x].size();
for(int i = 0; i < siz; i ++){
int son = G_t[x][i];
if( !vis[son] )
redfs(son);
}
}
int main(){
while( scanf("%d%d", &n, &m) != EOF ){
if( n == m && n == 0 )
return 0;
ans = 0;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i ++){
G[i].clear();
G_t[i].clear();
}
for(int i = 1; i <= m; i ++ ){
scanf("%d%d", &u, &v);
G[u].push_back(v);
G_t[v].push_back(u);
}
ds = 0;
for(int i = 1; i <= n; i ++ ){
if( !vis[i] )
dfs(i);
}
memset(vis, 0, sizeof(vis));
for(int i = n; i >= 1; i -- ){
if( !vis[time[i]] ){
redfs(time[i]);
ans ++;
}
}
if( ans == 1 )
printf("Yes\n");
else printf("No\n");
}
}
tarjan
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
#define M 10005
vector<int>G[M];
stack<int>ss;
int n, m, u, v, time, ans;
int Low[M], DFN[M], c[M];
bool vis[M], flag;
inline void dfs(int x){
vis[x] = 1;
int son;
time++;
Low[x] = DFN[x] = time;
ss.push(x);
int siz = G[x].size();
for(int i = 0; i < siz; i ++){
son = G[x][i];
if( !DFN[son] ){
dfs(son);
Low[x] = min(Low[x], Low[son]);
}
else if( vis[son] )
Low[x] = min(Low[x], DFN[son]);
}
if( Low[x] == DFN[x] ){
ans ++;
while(1){
int t = ss.top();
ss.pop();
c[t] = ans;
if( t == x )
break;
}
}
}
int main(){
while( scanf("%d%d", &n, &m) != EOF ){
if( !n && !m )
return 0;
flag = time = ans = 0;
memset(vis, 0, sizeof(vis));
memset(DFN, 0, sizeof(DFN));
while( !ss.empty() )
ss.pop();
memset(G, 0, sizeof(G));
for(int i = 1; i <= m; i ++ ){
scanf("%d%d", &u, &v);
G[u].push_back(v);
}
for(int i = 1; i <= n; i ++){
if( !vis[i] )
dfs(i);
}
if( ans != 1 )
printf("No\n");
else printf("Yes\n");
}
return 0;
}