/*
题意:给出一个有向图,判断该图是否为仙人掌图.
这里有一个不错的关于仙人掌图性质分析文章:
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;
}
HDOJ3594-仙人掌图的判断
最新推荐文章于 2020-08-18 21:35:08 发布