• Poj 3177 Redundant Paths (双连通分支+节点统计)


    题目描述:

      给出一个无向的连通图,问最少加入几条边,才能使所给的图变为无桥的双连通图?

    解题思路:

      可以求出原图中所有的不包含桥的所有最大连通子图,然后对连通子图进行标记缩点,统计度为1的叶子节点leaf有多少个,答案就是(leaf+1)/2;

      这个题目有重边,在处理的时候要注意下。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxn = 5005;
     8 struct node
     9 {
    10     int to, next;
    11 } edge[maxn*2];
    12 
    13 int low[maxn], dfn[maxn], head[maxn], id[maxn], in[maxn];
    14 int stack[maxn], tot, ntime, cnt, top, In;
    15 void init ()
    16 {
    17     tot = ntime = cnt = top = In = 0;
    18     memset (in, 0, sizeof(in));
    19     memset (id, 0, sizeof(id));
    20     memset (low, 0, sizeof(low));
    21     memset (dfn, 0, sizeof(dfn));
    22     memset (head, -1, sizeof(head));
    23     memset (stack, 0, sizeof(stack));
    24 }
    25 void Add (int from, int to)
    26 {
    27     edge[tot].to = to;
    28     edge[tot].next = head[from];
    29     head[from] = tot++;
    30 }
    31 void Tarjan (int u, int father)
    32 {
    33     int k = 0;
    34     low[u] = dfn[u] = ++ntime;
    35     stack[top++] = u;
    36     for (int i=head[u]; i!=-1; i=edge[i].next)
    37     {
    38         int v = edge[i].to;
    39         if (v==father && !k)
    40            {//判定重边
    41                 k++;
    42                 continue;
    43            }
    44         if (!dfn[v])
    45         {
    46             Tarjan (v, u);
    47             low[u] = min (low[v], low[u]);
    48         }
    49         else
    50             low[u] = min (low[u], dfn[v]);
    51     }
    52     if (low[u] == dfn[u])
    53     {
    54         cnt ++;
    55         while (1)
    56         {//对同一个连通块内的点染色
    57             int v = stack[--top];
    58             id[v] = cnt;
    59             if (v == u)
    60                 break;
    61         }
    62     }
    63 }
    64 int main ()
    65 {
    66     int n, m;
    67     while (scanf ("%d %d", &n, &m) != EOF)
    68     {
    69         init ();
    70         while (m --)
    71         {
    72             int u, v;
    73             scanf ("%d %d", &u, &v);
    74             Add (u, v);
    75             Add (v, u);
    76         }
    77         for (int i=1; i<=n; i++)
    78             if (!dfn[i])
    79                 Tarjan (i, 0);
    80         for (int i=1; i<=n; i++)
    81             for (int j=head[i]; j!=-1; j=edge[j].next)
    82             {
    83                 int u = id[i];
    84                 int v = id[edge[j].to];
    85                 if (v != u)
    86                 {//统计缩点后的图中每个点的度
    87                     in[v] ++;
    88                     in[u] ++;
    89                 }
    90             }
    91         for (int i=1; i<=cnt; i++)
    92             if (in[i] == 2)//因为是无向图建图方式的原因,当度为2的时候才是叶子节点
    93                 In ++;
    94         printf ("%d
    ", (In+1)/2);
    95     }
    96     return 0;
    97 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    js实现input button从不可用变为可用
    eclipse工程名出现小红叉的解决办法
    jQuery的dataTables插件实现中文排序
    禁用鼠标选中DOM
    获取当前JS所在文件夹
    解决方案:在移动端输入框在软键盘弹出后位置矫正
    MUI版本升级更新程序IOS和andriod
    JavaScript输入表单数据正则验证规则
    Windows安裝PHP環境
    CentOS下安装PHP
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4668592.html
Copyright © 2020-2023  润新知