• 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
    ":"NO
    ");
    67     }
    68 }

    2018-12-06

  • 相关阅读:
    317 随笔
    316 随笔
    315 随笔
    python 第一章
    matlab 第四章 第一节 字符串 元胞
    matlab 第三章 第二节 多维数组
    matlab 第三章
    python 循环+break continue
    Springboot 教程 导入
    matlab 第二章 第三节 数值表示、变量及表达式
  • 原文地址:https://www.cnblogs.com/00isok/p/10080161.html
Copyright © 2020-2023  润新知