zoukankan      html  css  js  c++  java
  • HDU3394 Railway 求块 判断环

    对于我来说真是一道好题,一开始纠结为缩点跟求块,最后还是一个8字形的图no了我一下。

    /*
    *State: HDU3394 328MS 2052K 1918 B C++ 
    题意描述:
    *        公园有n个景点,公园的管理员计划要建m条道路,并且安排一
    *        些形成回路的参观路径,如果一条道路可以被多条回路共用,
    *        那么这条边是冲突边,如果不能形成环的路则为不需要的边,
    *        现在就是求无向图中冲突边和不需要边的条数
    *解题思路:
    *        把图分为多个块,然后判断每个块里面的边数,如果块的边数
    *        等于块的点数,那么该块只有一个环,如果块的边数大于块的
    *        点数,那么这个块中有多个环,并且这个块中的每条边都是多
    *        个环里面的一部分。
    *
    *
    *问题困惑:在一个没有连通分量的无向图中,带环的块一定是由一个只
    *        有两个点的块相连着的,对不对?第一次求块,缩过点,求过
    *        桥跟割边,但是想不到求块居然会遇到这么多麻烦,不过原因
    *        就是求块的过程中,遇到了从不一样的栈弹出。至于为什么不能
    *        放里面。还是个疑问。懂了,画个图就知道,如果弹到u,有可能
    *        别的块也被弹出来了,结果错,必须弹到v为止,才是最干净的。
    */
    View Code
      1 #include <iostream>
      2 #include <vector>
      3 using namespace std;
      4 
      5 const int MAXN = 10015;
      6 vector<int> vec[MAXN];
      7 int myS[MAXN], top;
      8 int dfn[MAXN], low[MAXN], step;
      9 int block[MAXN];
     10 
     11 //deal_cricle
     12 int vst[MAXN], inBlock[MAXN];
     13 int sol1, sol2;
     14 
     15 void addEdge(int u, int v)
     16 {
     17     vec[u].push_back(v);
     18     vec[v].push_back(u);
     19 }
     20 
     21 void init()
     22 {
     23     sol1 = sol2 = 0;
     24     step = top = 0;
     25     for(int i = 0; i < MAXN; i++)
     26     {
     27         myS[i] = 0;
     28         vec[i].clear();
     29         dfn[i] = low[i] = -1;
     30     }
     31 }
     32 
     33 void deal_circle()
     34 {
     35     int edgeNum = 0;
     36     memset(vst, 0, sizeof(vst));
     37     memset(inBlock, 0, sizeof(inBlock));
     38 
     39     for(int i = 1; i <= block[0]; i++)
     40     {
     41         inBlock[block[i]] = 1;
     42     }
     43 
     44     for(int i = 1; i <= block[0]; i++)
     45     {
     46         int u = block[i];
     47         for(unsigned j = 0; j < vec[u].size(); j++)
     48         {
     49             int v = vec[u][j]; 
     50             if(inBlock[v] == 1)
     51                 edgeNum++;
     52         }
     53     }
     54     edgeNum /= 2;
     55     if(edgeNum > block[0])
     56         sol2 += edgeNum;
     57     if(edgeNum < block[0])
     58         sol1 += edgeNum;
     59 }
     60 
     61 void tarjan_block(int n)
     62 {
     63     dfn[n] = low[n] = ++step;
     64     myS[top++] = n;
     65     for(unsigned i = 0; i < vec[n].size(); i++)
     66     {
     67         int son = vec[n][i];
     68         if(dfn[son] == -1)
     69         {
     70             tarjan_block(son);
     71             low[n] = min(low[n], low[son]);
     72             if(low[son] >= dfn[n])
     73             {
     74                 block[0] = 0;
     75                 
     76                 while(1)
     77                 {
     78                     block[++block[0]] = myS[top - 1];
     79                     if(myS[--top] == son)
     80                         break;
     81                 }
     82                 block[++block[0]] = n;
     83                 deal_circle();
     84             }
     85         }
     86         else
     87             low[n] = min(low[n], dfn[son]);
     88     }
     89 }
     90 
     91 int main(void)
     92 {
     93 
     94 #ifndef ONLINE_JUDGE
     95     freopen("in.txt", "r", stdin);
     96 #endif
     97 
     98     int n, m;
     99     while(scanf("%d %d", &n, &m) != EOF)
    100     {
    101         if(n == 0 && m == 0)
    102             break;
    103 
    104         init();
    105         int u, v;
    106         for(int i = 0; i < m; i++)
    107         {
    108             scanf("%d %d", &u, &v);
    109             addEdge(u, v);
    110         }
    111 
    112         for(int i = 0; i < n; i++)
    113         {
    114             if(dfn[i] == -1)
    115                 tarjan_block(i);
    116         }
    117 
    118         printf("%d %d\n", sol1, sol2);
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    linux配置Java环境变量(详细)
    linux下的挂载点和分区是什么关系
    VNC的安装与配置
    Linux下的字符集问题
    Freemarker学习中遇到的问题
    ABAP- INCLUDE Zxxx IF FOUND.
    ABAP读取工单状态 STATUS_READ
    WIN7系统设置wifi
    201702-增强记
    20170301 Excel 分多个sheet 导出
  • 原文地址:https://www.cnblogs.com/cchun/p/2641076.html
Copyright © 2011-2022 走看看