HDOJ3594-仙人掌圖的判斷

/*
題意:給出一個有向圖,判斷該圖是否爲仙人掌圖.
這裏有一個不錯的關於仙人掌圖性質分析文章:
    pdf:http://files.cnblogs.com/ambition/cactus_solution.pdf
代碼也是按照文章中的仙人掌圖的3個性質來做的.
*/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=21000;
const int MM=100000;

int index,n,en,head[NN],cou[NN],vis[NN],dfn[NN],low[NN];
bool flag;
struct Edge{
    int v,next;
    Edge() {}
    Edge(int _v,int _next):v(_v),next(_next) {}
} e[MM];
inline void add(int u,int v)
{
    e[en]=Edge(v,head[u]);
    head[u]=en++;
}

void dfs(int u)
{
    int v,i;
    if (!flag) return;
    dfn[u]=low[u]=++index;
    vis[u]=1;
    for (i=head[u]; i!=-1; i=e[i].next)
    {
        v=e[i].v;
        if (vis[v]==2) { flag=false; return; }//性質1
        if (!vis[v])
        {
            dfs(v);
            if (low[v]>dfn[u]) { flag=false; return; } //性質2
            if (low[v]<dfn[u])
            {
                cou[u]++;
                if (low[v]<low[u]) low[u]=low[v];
            }
        }
        else if (low[v]<dfn[u])
        {
            cou[u]++;
            if (low[v]<low[u]) low[u]=low[v];
        }
        if (cou[u]>1) { flag=false; return; }//性質3
    }
    vis[u]=2;
}

int main()
{
    int cas,u,v;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%d",&n);
        en=0;
        for (int i=1; i<=n; i++)
        {
            head[i]=-1;
            vis[i]=cou[i]=0;
        }
        while (scanf("%d%d",&u,&v),u|v) add(u+1,v+1);

        flag=true; index=0;
        dfs(1);
        if (!flag || index<n) puts("NO");
        else                  puts("YES");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章