HDU3594:Cactus(Tarjan)

来源:互联网 发布:厦门天心软件 编辑:程序博客网 时间:2024/06/05 22:56

传送门

题意:
有向图判断仙人掌。

定义一个有向图是仙人掌:
1.强连通。
2.每条边只在一个环中出现。

题解:Tarjan

看到网上很多AC代码改了样例的输入顺序就WA了,让人怀疑起HDU数据的真实性。

仙人掌图的分析

论文中漏掉了对前向边的讨论,其实前向边与横叉边本质相同,换了一种建边顺序而已。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>using namespace std;inline int read(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}const int Maxn=2e4+50,Maxm=5e4+50;int T,n,cnt,ind,vis[Maxn],dfn[Maxn],low[Maxn],ok;struct node{    node *nxt;    int to;}Pool[Maxm],*pool=Pool,*edge[Maxn];inline void push_back(node *&now,int to){    ++pool;pool->nxt=now;pool->to=to;now=pool;}inline void dfs(int now){    dfn[now]=++ind;low[now]=ind;++cnt;int res=0;    for(node *e=edge[now];e&&ok;e=e->nxt){        if(vis[e->to]){            ok=0;break;        }else if(dfn[e->to])low[now]=min(low[now],dfn[e->to]),++res;        else dfs(e->to),res+=(low[e->to]<dfn[now]),(low[e->to]>dfn[now])?(ok=0):0;    }    vis[now]=1;    (res>=2?ok=0:0);}int main(){    T=read();    while(T--){        n=read();cnt=0;ind=0;ok=1;pool=Pool;        for(int i=1;i<=n;i++)edge[i]=0,dfn[i]=0,low[i]=0,vis[i]=0;        int u,v;        while(scanf("%d%d",&u,&v),(u+v)){            ++u;++v;            push_back(edge[u],v);        }        dfs(1);        if(!ok||cnt!=n)puts("NO");        else puts("YES");    }}