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;
}

 

 

posted @ 2012-07-15 22:04  'wind  阅读(188)  评论(0编辑  收藏  举报