HDU 3594 Cactus (强连通+仙人掌图)

<题目链接>

<转载于 >>> >

题目大意:

给你一个图,让你判断他是不是仙人掌图。

仙人掌图的条件是:

1、是强连通图。

2、每条边在仙人掌图中只属于一个强连通分量。仙人掌图pdf说明>>>

解题分析:

1、首先得先熟练掌握tarjan算法的应用。

2、必须了解仙人掌图的三个性质:

(1).仙人掌dfs图中不能有横向边,简单的理解为每个点只能出现在一个强联通分量中。

(2).low[v]<dfn[u],其中u为v的父节点

(3).a[u]+b[u]<2 ,  a[u]为u节点的儿子节点中有a[u]个low值小于u的dfn值。b[u]为u的逆向边条数。

三个性质有一个不满足则不是仙人掌图。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 #define rep(i,s,t) for(int i=s;i<=t;i++)
 7 #define clr(a,b) memset(a,b,sizeof(a))
 8 const int N = 2e4+10;
 9 const int M = 5e4+10;
10 int head[N],dfn[N],low[N],belong[N],stk[N];
11 bool color[N],instk[N],ok;
12 int n,top,tot,index,scnt;
13 struct Edge{
14     int to,next;
15 }edge[M];
16 void init(){
17     tot=top=index=scnt=0;
18     clr(head,-1);clr(dfn,0);clr(low,0);clr(belong,0);
19     clr(stk,0);clr(instk,false);clr(color,false);
20 }
21 void addedge(int u,int v){
22     edge[tot].to=v,edge[tot].next=head[u];
23     head[u]=tot++;
24 }
25 void Tarjan(int u){
26     dfn[u]=low[u]=++index;
27     stk[++top]=u,instk[u]=true;
28     int cnt=0;
29     for(int i=head[u];~i;i=edge[i].next){
30         int v = edge[i].to;
31         if(color[v])ok=false;   //性质1
32         if(!dfn[v]){
33             Tarjan(v);
34             if(low[v]>dfn[u])ok=false; //性质2
35             if(low[v]<dfn[u])cnt++;    //u的子节点中low值小于dfn[u]值得个数
36             if(cnt==2)ok=false;
37             low[u]=min(low[u],low[v]);
38         }else if(instk[v]){
39             low[u]=min(low[u],dfn[v]);cnt++;
40             if(cnt==2)ok=false;     //性质3
41         }
42     }
43     if(dfn[u]==low[u]){
44         scnt++;
45         while(true){
46             int v=stk[top--];
47             instk[v]=false;
48             belong[v]=scnt;
49             if(v==u)break;
50         }
51     }
52     color[u]=true;
53 }
54 int main(){
55     int T;scanf("%d",&T);while(T--){
56         scanf("%d",&n);
57         init();
58         int u,v;while(scanf("%d%d",&u,&v),u||v){
59             u++,v++;
60             addedge(u,v);
61         }
62         ok=true;
63         rep(i,1,n) if(!dfn[i]) {
64             Tarjan(i);
65         }
66         printf((scnt==1&&ok==true)?"YES\n":"NO\n");
67     }
68 }

 

 

2018-12-06

posted @ 2018-12-06 22:47  悠悠呦~  阅读(389)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end