• UVALive


    Problem   UVALive - 5135 - Mining Your Own Business

    Time Limit: 5000 mSec

    Problem Description

    John Digger is the owner of a large illudium phosdex mine. The mine is made up of a series of tunnels that meet at various large junctions. Unlike some owners, Digger actually cares about the welfare of his workers and has a concern about the layout of the mine. Specifically, he worries that there may a junction which, in case of collapse, will cut off workers in one section of the mine from other workers (illudium phosdex, as you know, is highly unstable). To counter this, he wants to install special escape shafts from the junctions to the surface. He could install one escape shaft at each junction, but Digger doesn’t care about his workers that much. Instead, he wants to install the minimum number of escape shafts so that if any of the junctions collapses, all the workers who survive the junction collapse will have a path to the surface. Write a program to calculate the minimum number of escape shafts and the total number of ways in which this minimum number of escape shafts can be installed.

    Input

    The input consists of several test cases. The first line of each case contains a positive integer N (N ≤ 5·104) indicating the number of mine tunnels. Following this are N lines each containing two distinct integers s and t, where s and t are junction numbers. Junctions are numbered consecutively starting at 1. Each pair of junctions is joined by at most a single tunnel. Each set of mine tunnels forms one connected unit (that is, you can get from any one junction to any other). The last test case is followed by a line containing a single zero.

    Output

    For each test case, display its case number followed by the minimum number of escape shafts needed for the system of mine tunnels and the total number of ways these escape shafts can be installed. You may assume that the result fits in a signed 64-bit integer. Follow the format of the sample output.
     

    Sample Input

    9 1 3 4 1 3 5 1 2 2 6 1 5 6 3 1 6 3 2 6 1 2 1 3 2 4 2 5 3 6 3 7 0

    Sample Output

    Case 1: 2 4

    Case 2: 4 1

    题解:做这种题就是涨姿势,删掉一个点之后还能连通,对于无向图来说,双连通才能满足这条性质,因此着眼点就放在了双连通分量上。接下来通过点双连通分量缩点来考虑问题。因为一个割点可能属于多个v-BCC,设图中有p个割点和t个v-BCC,我们建立一张包含p+t个节点的新图,把每个v-BCC和每个割点都作为新图中的节点,并在每个割点与包含它的所有v-BCC之间连边。这张图就变成了一棵树或是一片森林。我们可以只考虑树的情况,因为森林中的树相互之间独立,方案数满足乘法原理。随便找个节点转成有根树,则所有叶子节点都是v-BCC(如果叶子节点是割点那把他删去并不会使连通分量数增加),很明显这些节点中都需要一个太平井,之后可以证明除了这些节点需要太平井之外,别的节点都不需要。首先割点节点都是不需要的,因为如果该节点连接的两个双连通分量都只依靠该节点的太平井,那么删去该点之后这两个双连通分量还需要两个太平井,而如果有了这两个太平井,显然割点处的太平井是不需要的,其次,除了叶节点之外的双连通分量节点都至少连接两个割点,因此不论删去哪个割点,该分量节点所在的联通块都至少包含一个叶子节点,因此该节点不需要太平井。之后就是乘法原理了,有个需要注意的地方就是如果整个图是一个BCC,之前的分析就不奏效了,需要重新考虑,不过这种情况很简单,想到了就没问题。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define REP(i, n) for (int i = 1; i <= (n); i++)
      6 #define sqr(x) ((x) * (x))
      7 
      8 const int maxn = 50000 + 10;
      9 const int maxm = 30 + 10;
     10 const int maxs = 10000 + 10;
     11 
     12 typedef long long LL;
     13 typedef pair<int, int> pii;
     14 typedef pair<double, double> pdd;
     15 
     16 const LL unit = 1LL;
     17 const int INF = 0x3f3f3f3f;
     18 const LL mod = 1000000007;
     19 const double eps = 1e-14;
     20 const double inf = 1e15;
     21 const double pi = acos(-1.0);
     22 
     23 struct Edge
     24 {
     25     int u, v;
     26 };
     27 
     28 int n, m;
     29 vector<int> G[maxn];
     30 int dfs_clock, bcc_cnt;
     31 int pre[maxn], is_cut[maxn], bccno[maxn];
     32 vector<int> bcc[maxn];
     33 stack<Edge> S;
     34 
     35 int dfs(int u, int fa)
     36 {
     37     int lowu = pre[u] = ++dfs_clock;
     38     int child = 0;
     39     for (auto v : G[u])
     40     {
     41         Edge e = (Edge){u, v};
     42         if (!pre[v])
     43         {
     44             S.push(e);
     45             child++;
     46             int lowv = dfs(v, u);
     47             lowu = min(lowu, lowv);
     48             if (lowv >= pre[u])
     49             {
     50                 is_cut[u] = 1;
     51                 bcc_cnt++;
     52                 bcc[bcc_cnt].clear();
     53                 for (;;)
     54                 {
     55                     Edge x = S.top();
     56                     S.pop();
     57                     if (bccno[x.u] != bcc_cnt)
     58                     {
     59                         bcc[bcc_cnt].push_back(x.u);
     60                         bccno[x.u] = bcc_cnt;
     61                     }
     62                     if (bccno[x.v] != bcc_cnt)
     63                     {
     64                         bcc[bcc_cnt].push_back(x.v);
     65                         bccno[x.v] = bcc_cnt;
     66                     }
     67                     if (x.u == u && x.v == v)
     68                     {
     69                         break;
     70                     }
     71                 }
     72             }
     73         }
     74         else if (pre[v] < pre[u] && v != fa)
     75         {
     76             S.push(e);
     77             lowu = min(lowu, pre[v]);
     78         }
     79     }
     80     if (fa < 0 && child == 1)
     81     {
     82         is_cut[u] = 0;
     83     }
     84     return lowu;
     85 }
     86 
     87 void find_bcc()
     88 {
     89     memset(pre, 0, sizeof(pre));
     90     memset(is_cut, 0, sizeof(is_cut));
     91     memset(bccno, 0, sizeof(bccno));
     92     dfs_clock = bcc_cnt = 0;
     93     for (int i = 0; i < n; i++)
     94     {
     95         if (!pre[i])
     96         {
     97             dfs(i, -1);
     98         }
     99     }
    100 }
    101 
    102 int iCase;
    103 
    104 int main()
    105 {
    106     ios::sync_with_stdio(false);
    107     cin.tie(0);
    108     freopen("input.txt", "r", stdin);
    109     //freopen("output.txt", "w", stdout);
    110     while (cin >> m && m)
    111     {
    112         for (int i = 0; i < maxn; i++)
    113         {
    114             G[i].clear();
    115         }
    116         n = 0;
    117         int u, v;
    118         for (int i = 0; i < m; i++)
    119         {
    120             cin >> u >> v;
    121             u--, v--;
    122             G[u].push_back(v);
    123             G[v].push_back(u);
    124             n = max(n, u);
    125             n = max(n, v);
    126         }
    127         find_bcc();
    128         LL ans1 = 0, ans2 = 1LL;
    129         for (int i = 1; i <= bcc_cnt; i++)
    130         {
    131             int cnt = 0;
    132             for (auto v : bcc[i])
    133             {
    134                 if (is_cut[v])
    135                     cnt++;
    136             }
    137             if (cnt == 1)
    138             {
    139                 ans1++;
    140                 ans2 *= (LL)bcc[i].size() - 1;
    141             }
    142         }
    143         if (bcc_cnt == 1)
    144         {
    145             ans1 = 2;
    146             ans2 *= (LL)bcc[1].size() * (bcc[1].size() - 1) / 2;
    147         }
    148         cout << "Case " << ++iCase << ": " << ans1 << " " << ans2 << endl;
    149     }
    150     return 0;
    151 }
  • 相关阅读:
    使用PhantomJS报warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '解决方法
    案例:执行 JavaScript 语句
    案例:网站模拟登录
    爬虫中Selenium和PhantomJS
    爬虫中采集动态HTML介绍
    Oracle系列十五 控制用户权限
    Oracle系列十四 序列、索引和同义词
    Oracle系列十三 视图
    多线程爬虫案例
    CentOS7静默安装Oracle 18g数据库(无图形化界面)
  • 原文地址:https://www.cnblogs.com/npugen/p/10748038.html
Copyright © 2020-2023  润新知