zoukankan      html  css  js  c++  java
  • UVA5135 Mining Your Own Business ( 无向图双连通分量)

    题目链接

    题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点。任意两个连接点之间最多只有一条隧道。任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱,求最少安装数量和方案。

    分析:本题相当于在一张无向图上选择尽量少的点涂黑(对应太平井),使任意一个点被删除后,每个连通分量都至少还有一个黑点。不同的连通分量最多有一个公共点即割点,将割点涂上是不划算的,因为删除割点后,要保证每个连通分量还要有黑点,所以还要在其他的连通分量中涂黑点,如果不涂割点,还能省一个呢,在一个点连通分量中涂两个黑点也是不划算的, 所以只有当一个点连通分量中含有一个割点,那么就涂 除了 割点 其他的点,因为,如果删除这个割点后,你得保证剩下的有一个黑点。 对于一个连通分量中含有 >= 2个割点,就不用涂了,因为他有两个割点不会全部删除,可以通向其他的连通分量的 太平井,

      1 #include <iostream>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <cstdio>
      5 #include <vector>
      6 #include <stack>
      7 using namespace std;
      8 typedef long long LL;
      9 const int Max = 50005;
     10 struct Edge
     11 {
     12     int u, v;
     13 };
     14 vector<int> G[Max], bcc[Max];
     15 int pre[Max], bccno[Max], iscut[Max];
     16 int dfs_clock, bcc_cnt;
     17 stack<Edge> S;
     18 int dfs(int u, int fa)
     19 {
     20     int lowu = pre[u] = ++dfs_clock;
     21     int Size = G[u].size();
     22     int child = 0;
     23     for (int i = 0; i < Size; i++)
     24     {
     25         int v = G[u][i];
     26         Edge e;
     27         e.u = u;
     28         e.v = v;
     29         if (!pre[v])
     30         {
     31             S.push(e);
     32             child++;
     33             int lowv = dfs(v, u);
     34             lowu = min(lowu, lowv);
     35             if (lowv >= pre[u])
     36             {
     37                 iscut[u] = true;
     38                 bcc_cnt++;
     39                 bcc[bcc_cnt].clear();
     40                 for (; ;)
     41                 {
     42                     Edge x = S.top();
     43                     S.pop();
     44                     if (bccno[x.u] != bcc_cnt)
     45                     {
     46                         bccno[x.u] = bcc_cnt;
     47                         bcc[bcc_cnt].push_back(x.u);
     48                     }
     49                     if (bccno[x.v] != bcc_cnt)
     50                     {
     51                         bccno[x.v] = bcc_cnt;
     52                         bcc[bcc_cnt].push_back(x.v);
     53                     }
     54                     if (x.u == u && x.v == v)
     55                         break;
     56                 }
     57             }
     58         }
     59         else if (pre[v] < pre[u] && v != fa)
     60             lowu = min(lowu, pre[v]);
     61     }
     62     if (child == 1 && fa < 0)
     63         iscut[u] = 0;
     64     return lowu;
     65 }
     66 void find_bcc(int n)
     67 {
     68     if (!S.empty())
     69         S.pop();
     70     memset(pre, 0, sizeof(pre));
     71     memset(bccno, 0, sizeof(bccno));
     72     memset(iscut, 0, sizeof(iscut));
     73     dfs_clock = bcc_cnt = 0;
     74     for (int i = 1; i <= n; i++)
     75     {
     76         if (!pre[i])
     77             dfs(i, -1);
     78     }
     79 }
     80 int main()
     81 {
     82     int test = 0, n;
     83     while (scanf("%d", &n) != EOF && n)
     84     {
     85         int u, v, temp = -1;
     86         for (int i = 1; i < Max; i++)
     87             G[i].clear();  //清空
     88         for (int i = 1; i <= n; i++)
     89         {
     90             scanf("%d%d", &u, &v);
     91             G[u].push_back(v);
     92             G[v].push_back(u);
     93             temp = max(temp, max(u, v));  // 找到最大的点
     94         }
     95         find_bcc(temp);  // 找连通分量
     96         LL ans1 = 0, ans2 = 1;
     97         for (int i = 1; i <= bcc_cnt; i++)
     98         {
     99             int cut_cnt = 0;
    100             int Size = bcc[i].size();
    101             for (int j = 0; j < Size; j++)
    102             {
    103                 if (iscut[ bcc[i][j] ])
    104                     cut_cnt++;
    105             }
    106             if (cut_cnt == 1)
    107             {
    108                 ans1++;
    109                 ans2 *= (LL)(Size - 1);
    110             }
    111         }
    112         if (bcc_cnt == 1)
    113         {
    114             ans1 = 2;
    115             ans2 = (LL) bcc[1].size() * (LL) (bcc[1].size() - 1) / 2;
    116         }
    117         printf("Case %d: %lld %lld
    ", ++test, ans1, ans2);
    118     }
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    ABAP接口用法
    监听textarea数值变化
    The first step in solving any problem is recognizing there is one.
    Wrinkles should merely indicate where smiles have been.
    God made relatives.Thank God we can choose our friends.
    Home is where your heart is
    ABAP跳转屏幕
    Python 工具包 werkzeug 初探
    atom通过remote ftp同步本地文件到远程主机的方法
    Mongodb学习笔记一
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5350050.html
Copyright © 2011-2022 走看看