题意:为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。
想法:tarjan求连通分量。
#include<iostream> #include<cstdio> #include<cstring> #include<stack> #define mm(x) memset(x,0,sizeof(x)) using namespace std; const int N=10000+5; const int M=100000+5; int dfn[N],low[N],paint[N],col,index; int instack[N]; stack<int>s; struct node { int v,next; }e[M]; int head[N],cnt; void Init() { while(!s.empty()) s.pop(); memset(head,-1,sizeof(head)); index=col=1; cnt=0; mm(dfn); mm(low); mm(instack); mm(paint); } void add(int a,int b) { e[cnt].v=b; e[cnt].next=head[a]; head[a]=cnt++; } int Min(int a,int b) { if(a<b) return a; return b; } void tarjan(int u) { dfn[u]=low[u]=index++; instack[u]=1; s.push(u); for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(!dfn[v]) { tarjan(v); low[u]=Min(low[u],low[v]); } else if(instack[v]) { low[u]=Min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { int k=s.top(); while(u!=k) { s.pop(); paint[k]=col; instack[k]=0; k=s.top(); } s.pop(); paint[u]=col; instack[u]=0; col++; } } int main() { int n,m; while(cin>>n>>m,m+n) { Init(); for(int i=1;i<=m;i++) { int a,b; cin>>a>>b; add(a,b); } for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i); } col--; if(col==1) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }