【题目描述】
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。
【输入格式】
输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。
【输出格式】
对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
【分析】
强连通分量模板,tarjan跑一边,,看sum是不是1就可以了。
【代码】
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 10 using namespace std; 11 12 #define ms(a,b) memset(a,b,sizeof(a)) 13 14 const int maxn=10010; 15 const int maxm=100010; 16 17 struct Edge{ 18 int to,next; 19 }edge[maxm<<1]; 20 21 int vis[maxn],dfn[maxn],low[maxn],belong[maxn],stack[maxn]; 22 int head[maxm]; 23 int top,sum,dep,nedge,n,m; 24 25 inline int read() 26 { 27 int X=0,w=0; char ch=0; 28 while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} 29 while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); 30 return w?-X:X; 31 } 32 33 void add_edge(int a,int b) 34 { 35 edge[nedge]=(Edge){b,head[a]}; head[a]=nedge++; 36 } 37 38 void tarjan(int u) 39 { 40 dfn[u]=low[u]=++dep; 41 stack[top++]=u; 42 vis[u]=1; 43 for (int i=head[u];i!=-1;i=edge[i].next) 44 { 45 int v=edge[i].to; 46 if (!dfn[v]) 47 { 48 tarjan(v); 49 low[u]=min(low[u],low[v]); 50 } 51 else 52 { 53 if (vis[v]) low[u]=min(low[u],dfn[v]); 54 } 55 } 56 int j; 57 if (dfn[u]==low[u]) 58 { 59 sum++; 60 do { 61 j=stack[--top]; 62 belong[j]=sum; 63 vis[j]=0; 64 } 65 while (u!=j); 66 } 67 } 68 69 void init() 70 { 71 nedge=0,top=0,sum=0,dep=0; 72 ms(head,-1); 73 ms(stack,0); 74 ms(dfn,0); 75 ms(vis,0); 76 ms(belong,0); 77 ms(low,0); 78 } 79 80 int main() 81 { 82 while (1) 83 { 84 init(); 85 n=read(),m=read(); 86 if (n==0 && m==0) break; 87 for (int i=1;i<=m;i++) 88 { 89 int a=read(),b=read(); 90 add_edge(a,b); 91 } 92 for (int i=1;i<=n;i++) 93 { 94 if (!dfn[i]) tarjan(i); 95 } 96 if (sum>1) printf("No\n"); 97 else printf("Yes\n"); 98 } 99 return 0;100 }