爲了訓練小希的方向感,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
思路:塔尖模板求 強連通分量 。此題是判斷所有的點能否構成 一個強連通分量
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int fir[100010],nex[100010],to[100010];
int col,tot,top,num;
int co[100010];
int dfn[100010];
int low[100010];
int a[100010];
int build(int x,int y)//鄰接表
{
to[++tot]=y;
nex[tot]=fir[x];
fir[x]=tot;
}
void tarjan(int u)//塔尖算法的核心
{
dfn[u]=low[u]=++num;
a[++top]=u;
for(int i=fir[u]; i>0; i=nex[i])
{
int v=to[i];
if(dfn[v]==0)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else
{
if(!co[v])
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
co[u]=++col;
while(a[top]!=u)
{
co[a[top]]=col;
--top;
}
--top;
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
memset(fir,0,sizeof(fir));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(co,0,sizeof(co));
memset(to,0,sizeof(to));
memset(a,0,sizeof(a));
int x,y;
tot=0,col=0,top=0;
for(int i=0; i<m; i++)
{
scanf("%d%d",&x,&y);
build(x,y);
}
for(int i=1; i<=n; i++)
if(!dfn[i])
tarjan(i);
if(col==1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}