• 【HDU 3594 Cactus】tarjan+仙人掌图


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3594

    题目大意:给你一个图,让你判断他是不是仙人掌图。

    仙人掌图的条件是:

    1、是强连通图。

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

    仙人掌图介绍   -->  https://files.cnblogs.com/ambition/cactus_solution.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 <algorithm>
     2 #include <vector>
     3 #include <iostream>
     4 #include <cstdio>
     5 #include <cstring>
     6 using namespace std;
     7 
     8 const int maxn=20005;
     9 int  dfn[maxn], low[maxn], stack[maxn], belong[maxn];
    10 bool instack[maxn], color[maxn], ok;
    11 int top, scnt, Index, n;
    12 vector<int>vt[maxn];
    13 
    14 void Init_tarjan()
    15 {
    16     top=scnt=Index=0;
    17     for(int i=1; i<=n; i++) dfn[i]=low[i]=instack[i]=color[i]=0;
    18 }
    19 
    20 void tarjan(int u)
    21 {
    22     stack[++top]=u;
    23     dfn[u]=low[u]=++Index;
    24     instack[u]=1;
    25     int cnt=0;
    26     for(int i=0; i<vt[u].size(); i++)
    27     {
    28         int v=vt[u][i];
    29         if(color[v]) ok=false; ///!!!性质1
    30         if(!dfn[v])
    31         {
    32             tarjan(v);
    33             if(low[v]>dfn[u]) ok=false; ///!!!性质2
    34             if(low[v]<dfn[u]) cnt++;
    35             if(cnt==2) ok=false;
    36             low[u]=min(low[u],low[v]);
    37         }
    38         else if(instack[v])
    39         {
    40             low[u]=min(low[u],dfn[v]);  ///这里把时间戳dfn写成了low,错误了好几次
    41             cnt++;
    42             if(cnt==2) ok=false;   ///!!!性质3
    43         }
    44     }
    45     if(low[u]==dfn[u]) ///有向图缩点
    46     {
    47         int v;
    48         scnt++; ///强连通分量的个数
    49         do
    50         {
    51             v=stack[top--];
    52             instack[v]=0;
    53             belong[v]=scnt;///!让一个强连通分量缩成一个点
    54         }while(u!=v);
    55     }
    56     color[u]=1;
    57 }
    58 
    59 int main()
    60 {
    61     int  T, u, v;
    62     cin >> T;
    63     while(T--)
    64     {
    65       for(int i=0; i<maxn; i++)
    66         vt[i].clear();
    67       cin >> n;
    68       while(1)
    69       {
    70          scanf("%d%d",&u,&v);
    71          if(u+v==0) break;
    72          vt[u+1].push_back(v+1);
    73       }
    74       Init_tarjan();
    75       ok=true;
    76       for(int i=1; i<=n; i++)
    77         if(!dfn[i]) tarjan(i);
    78       printf((scnt==1&&ok==true)?"YES\n":"NO\n");
    79     }
    80 }
  • 相关阅读:
    Linq 中 表连接查询
    Html Div 拖拽
    持续集成:TestNG中case之间的关系
    测试技术培训:如何测试磁盘写的速度
    POPTEST 测试开发 免费培训课程报名
    接上文 下面是一段示例代码
    老李分享:android手机测试之适配(1)
    (转)POPTEST创始人李爱然:谢谢,帮助我的朋友!!!!
    性能调优之SQL优化
    大数据测试之Hadoop的基本概念
  • 原文地址:https://www.cnblogs.com/kane0526/p/2817309.html
Copyright © 2020-2023  润新知