zoukankan      html  css  js  c++  java
  • HDU3594 Cactus 判断是否为仙人掌图 难度中

    这道题目挺有意思,amb大牛还发了那个强大的仙人掌图剖析的pdf,自己yy了一种解法,由于HDU上的数据够弱,

    暂时没有发现自己的代码有啥错误的。网上各种代码错误,还各种ac了~~这道题的数据,汗~~

    可以测测这一组数据:

    1
    4
    0 1
    1 2
    2 0
    2 3
    3 2
    3 0
    0 0

    正确输出:no

    /*
    *State: HDU3594 78MS 2644K 3134 B C++ 
    *题目大意:
    *        给一个有向图,判断这个有向图是否为仙人掌图。
    *        仙人掌图满足:1、是强连通图 2、每条边都只属于一个环
    *解题思路:
    *        判断强连通比较好做,主要是要判断每条边都属于一个环。
    *        我想到了用块来判断,但是只用块判断过无向图,但是用笔模拟
    *        了下,感觉有向图跟无向图都是一样的判断。
    *        就保存了有向图跟无向图,想想一个强连通图是仙人掌图,那么
    *        它从无向图上看一定是多个块之间靠一个点连接起来。那么好做
    *        把它保存为无向图,然后求块,判断每个块中边的个数是否等于
    *        块中点的个数,即可判断是否每条边只属于一个环。
    *解题感想;
    *        1a了,没想到这么神奇,看来专注是必须的。
    *        这道题目的数据比较水,该方法还有待验证。
    *        该题值得慢慢品味
    */
    View Code
      1 #include <iostream>
      2 using namespace std;
      3 
      4 const int MAXN = 20005;
      5 const int MAXE = 50005;
      6 
      7 typedef struct _node
      8 {
      9     int v, next, isdir;
     10     _node() :isdir(0) {};
     11 }N;
     12 
     13 N edge[MAXE * 2];
     14 int head[MAXN], cntEdge, myS[MAXN], top;
     15 int inS[MAXN], isScc;
     16 
     17 int bMyS[MAXN], bTop;
     18 int low[MAXN], dfn[MAXN], step;
     19 
     20 int block[MAXN], isOneCir;
     21 
     22 void init()
     23 {
     24     top = bTop = 0;
     25     cntEdge = 0;
     26     isScc = false;
     27     isOneCir = true;
     28     for(int i = 0; i < MAXN; i++)
     29     {
     30         inS[i] = 0;
     31         head[i] = -1;
     32     }
     33 }
     34 
     35 void addEdge(int u, int v)
     36 {
     37     edge[cntEdge].v = v;
     38     edge[cntEdge].isdir = 1;
     39     edge[cntEdge].next = head[u];
     40     head[u] = cntEdge++;
     41 
     42     edge[cntEdge].v = u;
     43     edge[cntEdge].next = head[v];
     44     edge[cntEdge].isdir = 0;
     45     head[v] = cntEdge++;
     46 }
     47 
     48 void tarjan_scc(int n, int toln)
     49 {
     50     dfn[n] = low[n] = ++step;
     51     myS[top++] = n;
     52     inS[n] = 1;
     53     for(int f = head[n]; f != -1; f = edge[f].next)
     54     {
     55         if(!edge[f].isdir)
     56             continue;
     57         int son = edge[f].v;
     58         if(dfn[son] == -1)
     59         {
     60             tarjan_scc(son, toln);
     61             low[n] = min(low[n], low[son]);
     62         }
     63         else if(inS[son] == 1)
     64             low[n] = min(low[n], dfn[son]);
     65     }
     66     if(low[n] == dfn[n] && top != 0)
     67     {
     68         int _cnt = 0;
     69         int tmp;
     70         do
     71         {
     72             tmp = myS[--top];
     73             _cnt++;
     74         }while(top != 0 && tmp != n);
     75         if(_cnt == toln)
     76             isScc = true;
     77     }
     78 }
     79 
     80 void judge()
     81 {
     82     int vst[MAXN] = {0};
     83     for(int i = 1; i <= block[0]; i++)
     84     {
     85         vst[block[i]] = 1;
     86     }
     87     int u, v, sum = 0;
     88     for(int i = 1; i <= block[0]; i++)
     89     {
     90         u = block[i];
     91         for(int f = head[u]; f != -1; f = edge[f].next)
     92         {
     93             v = edge[f].v;
     94             if(vst[v])
     95                 sum++;
     96         }
     97     }
     98     sum /= 2;
     99     if(isOneCir == true && sum != block[0])
    100         isOneCir = false;
    101 }
    102 
    103 //求块
    104 void tarjan_block(int n)
    105 {
    106     dfn[n] = low[n] = ++step;
    107     bMyS[bTop++] = n;
    108 
    109     for(int f = head[n]; f != -1; f = edge[f].next)
    110     {
    111         int son = edge[f].v;
    112         if(dfn[son] == -1)
    113         {
    114             tarjan_block(son);
    115             low[n] = min(low[n], low[son]);
    116 
    117             if(low[son] >= dfn[n])
    118             {
    119                 block[0] = 0;
    120                 int tmp;
    121                 while(true)
    122                 {
    123                     tmp = bMyS[bTop - 1];
    124                     block[++block[0]] = tmp;
    125                     if(bMyS[--bTop] == son)
    126                         break;
    127                 }
    128                 block[++block[0]] = n;
    129                 judge();
    130             }
    131         }
    132         else
    133             low[n] = min(low[n], dfn[son]);
    134     }
    135 }
    136 
    137 int main(void)
    138 {
    139 #ifndef ONLINE_JUDGE
    140     freopen("in.txt", "r", stdin);
    141 #endif
    142 
    143     int cas;
    144     scanf("%d", &cas);
    145     while(cas--)
    146     {
    147         init();
    148         int n, u, v;
    149         scanf("%d", &n);
    150         while(scanf("%d %d", &u, &v), u || v)
    151         {
    152             addEdge(u, v);
    153         }
    154         for(int i = 0; i < MAXN; i++)
    155             dfn[i] = low[i] = -1;
    156         step = 0;
    157         tarjan_scc(0, n);
    158 
    159         //强连通才继续判断
    160         for(int i = 0; i < MAXN; i++)
    161             dfn[i] = low[i] = -1;
    162         step = 0;
    163 
    164         if(isScc)
    165             tarjan_block(0);
    166 
    167         if(isScc && isOneCir)
    168             printf("YES\n");
    169         else
    170             printf("NO\n");
    171     }
    172     return 0;
    173 }
  • 相关阅读:
    【BZOJ4445】【SCOI2015】—小凸想跑步(半平面交)
    【BZOJ4444】【SCOI2015】—国旗计划(倍增+贪心)
    【BZOJ4443】【SCOI2015】—小凸玩矩阵(二分+最大匹配)
    【BZOJ4518】【SDOI2016】—征途(斜率优化dp)
    【BZOJ4199】【NOI2015】—品酒大会(后缀数组)
    【BZOJ3160】【2013湖北互测week1】—万径人踪灭(FFT+Manacher)
    ifconfig 查看网卡信息
    rm:删除目录和文件
    查看进程:ps
    wget 下载命令
  • 原文地址:https://www.cnblogs.com/cchun/p/2641080.html
Copyright © 2011-2022 走看看