HDOJ3594-仙人掌图的判断

53 篇文章 1 订阅
/*
题意:给出一个有向图,判断该图是否为仙人掌图.
这里有一个不错的关于仙人掌图性质分析文章:
    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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值