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
中文题意不解释。。。
裸强连通分量
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define MOD 100000 #define inf 1<<29 #define LL long long #define MAXN 10010 #define MAXM 200010 using namespace std; struct Edge { int to,next; } edge[MAXM]; int head[MAXM],tot; int low[MAXN],DFN[MAXN],belong[MAXN];///belong 的值为1-scc int index,top; int scc ; ///强连通分量 bool inStack[MAXN]; int num[MAXN],stack[MAXN]; ///num为各个强连通分量包含的点的个数,数组编号1-scc num数组不一定需要,结合实际情况 void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++ ; } void Tarjan(int u) { int v; low[u] = DFN[u] = ++index; stack[top++] = u; inStack[u] = true; for(int i=head[u] ; i!=-1 ; i=edge[i].next) { v = edge[i].to; if( !DFN[v] ) { Tarjan(v); if(low[u]>low[v]) low[u] = low[v]; } else if( inStack[v] && low[u] > DFN[v]) low[u] = DFN[v]; } if(low[u] == DFN[u]) { scc++; do { v=stack[--top]; ///清空当前强连通分量栈 必须清空 inStack[v] = false; belong[v]=scc; num[scc]++; } while(v!=u); } } void solve(int N) { for(int i=1; i<=N ; i++) if( !DFN[i] ) Tarjan(i); } void init() { tot = index = scc = top =0; memset(head,-1,sizeof(head)); memset(DFN,0,sizeof(DFN)); memset(inStack,false,sizeof(inStack)); memset(num,0,sizeof(num)); } int main () { int n,m,Case=1; while(~scanf("%d%d",&n,&m)&&!(m==0&&n==0)) { int u,v; init(); for(int i=0; i<m; i++) { scanf("%d%d",&u,&v); addedge(u,v); // addedge(v,u); } solve(n); if(scc <= 1) printf("%s ","Yes"); else printf("%s ","No"); } return 0; }