这是一道典型的强连通的题目。 所谓强连通,就是对于一个有向图,若一个集合内任意2点都能过互相达,于是这个几何就是一个强连通分量。 对于任意图,都可以分解 人多个不相交的强连通集合。 对于这题目,只要用著名的tarjin算法对原图进行一次强连通缩点,若说有点都在一个强连通分量,就是yes, 否者no。 这里可以用并查集。
VIEW CODE
//#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<map> #include<vector> #include<set> #include<ctime> #include<stdlib.h> using namespace std; const int mmax= 10010; const int mod=1000000007; struct node { int st,en; int next; }E[100010]; int p[mmax],fa[mmax]; int num; void init() { memset(p,-1,sizeof p); num=0; } void add(int st,int en) { E[num].st=st; E[num].en=en; E[num].next=p[st]; p[st]=num++; } int find(int x) { if(x==fa[x]) return x; return fa[x]=find(fa[x]); } int times,pp; int low[mmax],dfn[mmax],Q[mmax]; bool instack[mmax]; void tarjin(int u) { dfn[u]=low[u]=++times; Q[++pp]=u; instack[u]=1; for(int i=p[u];i+1;i=E[i].next) { int v=E[i].en; if(!dfn[v]) { tarjin(v); if(low[u]>low[v]) low[u]=low[v]; } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { while(pp) { int x=Q[pp--]; instack[x]=0; if(x==u) break; int xx=find(x); fa[xx]=u; } } } int main() { int n,m; while(cin>>n>>m && n+m) { init(); times=pp=0; memset(dfn,0,sizeof dfn); memset(instack,0,sizeof instack); for(int i=0;i<=n;i++) fa[i]=i; for(int i=0;i<m;i++) { int u,v; scanf("%d %d",&u,&v); add(u,v); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjin(i); int cnt=0; for(int i=1;i<=n;i++) if(i==find(i)) cnt++; if(cnt-1) puts("No"); else puts("Yes"); } return 0; }
原文地址:http://blog.csdn.net/u012127882/article/details/43409455