HDU 3594 Cactus【强连通分量】
题意: 给一个有向图,问该图是不是强连通图,且图中每条边仅属于一个环。
分析: 如果一个节点已经在栈中,当该点被访问到即又出现了一条连向该点的横向边,且该点不是根节点,这条边
就是一条属于两个环的边。
code:
View Code
View Code #include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)) const int maxn=20002; struct node { int to; int next; }e[50005]; int tot; int head[maxn]; void add(int s,int u) { e[tot].to=u; e[tot].next=head[s]; head[s]=tot++; } bool flag; bool ins[maxn]; int dfn[maxn],low[maxn],stack[maxn]; int sn,ti,top; void tarjan(int u) { dfn[u]=low[u]=++ti; stack[++top]=u; ins[u]=true; int i,k; for(i=head[u];i;i=e[i].next) { k=e[i].to; if(dfn[k]==0) { tarjan(k); if(low[k]<low[u]) low[u]=low[k]; } else if(ins[k]) { if(dfn[k]<low[u]) low[u]=dfn[k]; if(dfn[k]!=low[k]) // 如果该点不是根节点 flag=true; } if(flag) return; } if(dfn[u]==low[u]) { sn++; if(sn>1) return; do { k=stack[top--]; ins[k]=false; } while(k!=u); } } int main() { int t,i,k,a,b,n; scanf("%d",&t); while(t--) { scanf("%d",&n); tot=1; sn=ti=0; top=-1; flag=false; clr(head); clr(ins); clr(dfn); clr(low); while(scanf("%d%d",&a,&b),a||b) add(a,b); for(i=0;i<n;i++) if(dfn[i]==0) tarjan(i); if(flag||sn>1) printf("NO\n"); else printf("YES\n"); } return 0; }