ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[HNOI2012]矿场搭建

2019-02-02 16:49:14  阅读:320  来源: 互联网

标签:pre 矿场 int top HNOI2012 bccno low bs 搭建


题目传送门

分析:

这道题是跟$Tarjan$有关的一题。

如果某一个点双连通分量中没有割顶,则这个点双的答案为$2$。因为塌了任何一个点,其他任意两点仍然连通。防止塌的点就是救援口,所以要设置$2$个。

如果某一个点双连通分量中有一个割顶,说明至少有两个点双公用这一个割顶。所以必须保证每个点双中除割顶的其他任意一点是救援口,且只需一个。如果塌了割点,对每个点双无影响;如果塌了其中一个救援口,该点双能通过割点到达另一个点双的救援口。

如果某一个点双连通分量中有两个或以上的割顶,则它不需要救援口。因为它如果塌了其中的一个割点,能通过另一个割点到达其他的救援口。

最优性证明:以上方案中没有任何一个多余救援口,且能保证题意成立,且无法找到更优的方案。

第二问方案数:将每个点双根据以上三种情况进行统计,累乘即可。

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define re register
  6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
  7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
  8 #define maxx(a, b) a = max(a, b);
  9 #define minn(a, b) a = min(a, b);
 10 #define LL long long
 11 #define inf (1 << 30)
 12 
 13 const int maxn = 1000 + 10;
 14 
 15 struct Edge {
 16     int u, v, pre;
 17 };
 18 
 19 struct Graph {
 20     Edge edges[maxn << 1];
 21     int n, m, G[maxn];
 22     void init() {
 23         m = 0;
 24         memset(G, 0, sizeof(G));
 25     }
 26     void add(int u, int v) {
 27         edges[++m] = (Edge){u, v, G[u]};
 28         G[u] = m;
 29     }
 30     int dfs_clock, iscut[maxn], low[maxn], pre[maxn];
 31     stack<pair<int, int> > S;
 32     int bccno[maxn], bs, cnt[maxn];
 33     vector<int> bcc[maxn];
 34     void dfs(int u, int fa) {
 35         low[u] = pre[u] = ++dfs_clock;
 36         int child = 0;
 37         for (register int i = G[u]; i; i = edges[i].pre) {
 38             int v = edges[i].v;
 39             if (!pre[v]) {
 40                 S.push(make_pair(u, v));
 41                 child++;
 42                 dfs(v, u);
 43                 minn(low[u], low[v]);
 44                 if (low[v] >= pre[u]) {
 45                     iscut[u] = 1;
 46                     bcc[++bs].clear();
 47                     for (;;) {
 48                         pair<int, int> top = S.top(); S.pop();
 49                         if (bccno[top.first] != bs) bccno[top.first] = bs, bcc[bs].push_back(top.first);
 50                         if (bccno[top.second] != bs) bccno[top.second] = bs, bcc[bs].push_back(top.second);
 51                         if (top.first == u && top.second == v) break;
 52                     }
 53                 }
 54             }
 55             else if (v != fa) {
 56                 //S.push(make_pair(u, v));
 57                 minn(low[u], pre[v]);
 58             }
 59         }
 60         if (u == fa && child == 1) iscut[u] = 0;
 61     }
 62     pair<int, LL> tarjan() {
 63         memset(pre, 0, sizeof(pre));
 64         memset(low, 0, sizeof(low));
 65         memset(iscut, 0, sizeof(iscut));
 66         memset(bccno, 0, sizeof(bccno));
 67         bs = 0;
 68         rep(i, 1, n)
 69             if (!pre[i])
 70                 dfs(i, i);
 71         memset(cnt, 0, sizeof(cnt));
 72         rep(i, 1, bs)
 73             for (register int x = 0; x < bcc[i].size(); x++)
 74                 cnt[i] += iscut[bcc[i][x]] ? 1 : 0;
 75         LL ans = 1; int sum = 0;
 76         rep(i, 1, bs) {
 77             int tot = bcc[i].size();
 78             if (!cnt[i]) sum += 2, ans *= (tot-1)*tot/2;
 79             else if (cnt[i] == 1)
 80                 sum++, ans *= tot-1;
 81         }
 82         return make_pair(sum, ans);
 83     }
 84 } G;
 85 
 86 int n, T = 0;
 87 
 88 int main() {
 89     while (~scanf("%d", &n)) {
 90         T++;
 91         int N = 0;
 92         if (!n) break;
 93         G.init();
 94         rep(i, 1, n) {
 95             int u, v;
 96             scanf("%d%d", &u, &v);
 97             G.add(u, v);
 98             G.add(v, u);
 99             N = max(N, max(u, v));
100         }
101         G.n = N;
102         pair<int, LL> ans = G.tarjan();
103         printf("Case %d: %d %lld\n", T, ans.first, ans.second);
104     }
105     return 0;
106 }

 

标签:pre,矿场,int,top,HNOI2012,bccno,low,bs,搭建
来源: https://www.cnblogs.com/ac-evil/p/10348710.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有