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
Sample Input
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,之前的分析就不奏效了,需要重新考虑,不过这种情况很简单,想到了就没问题。
#include <bits/stdc++.h> using namespace std; #define REP(i, n) for (int i = 1; i <= (n); i++)
#define sqr(x) ((x) * (x)) const int maxn = + ;
const int maxm = + ;
const int maxs = + ; typedef long long LL;
typedef pair<int, int> pii;
typedef pair<double, double> pdd; const LL unit = 1LL;
const int INF = 0x3f3f3f3f;
const LL mod = ;
const double eps = 1e-;
const double inf = 1e15;
const double pi = acos(-1.0); struct Edge
{
int u, v;
}; int n, m;
vector<int> G[maxn];
int dfs_clock, bcc_cnt;
int pre[maxn], is_cut[maxn], bccno[maxn];
vector<int> bcc[maxn];
stack<Edge> S; int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = ;
for (auto v : G[u])
{
Edge e = (Edge){u, v};
if (!pre[v])
{
S.push(e);
child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if (lowv >= pre[u])
{
is_cut[u] = ;
bcc_cnt++;
bcc[bcc_cnt].clear();
for (;;)
{
Edge x = S.top();
S.pop();
if (bccno[x.u] != bcc_cnt)
{
bcc[bcc_cnt].push_back(x.u);
bccno[x.u] = bcc_cnt;
}
if (bccno[x.v] != bcc_cnt)
{
bcc[bcc_cnt].push_back(x.v);
bccno[x.v] = bcc_cnt;
}
if (x.u == u && x.v == v)
{
break;
}
}
}
}
else if (pre[v] < pre[u] && v != fa)
{
S.push(e);
lowu = min(lowu, pre[v]);
}
}
if (fa < && child == )
{
is_cut[u] = ;
}
return lowu;
} void find_bcc()
{
memset(pre, , sizeof(pre));
memset(is_cut, , sizeof(is_cut));
memset(bccno, , sizeof(bccno));
dfs_clock = bcc_cnt = ;
for (int i = ; i < n; i++)
{
if (!pre[i])
{
dfs(i, -);
}
}
} int iCase; int main()
{
ios::sync_with_stdio(false);
cin.tie();
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
while (cin >> m && m)
{
for (int i = ; i < maxn; i++)
{
G[i].clear();
}
n = ;
int u, v;
for (int i = ; i < m; i++)
{
cin >> u >> v;
u--, v--;
G[u].push_back(v);
G[v].push_back(u);
n = max(n, u);
n = max(n, v);
}
find_bcc();
LL ans1 = , ans2 = 1LL;
for (int i = ; i <= bcc_cnt; i++)
{
int cnt = ;
for (auto v : bcc[i])
{
if (is_cut[v])
cnt++;
}
if (cnt == )
{
ans1++;
ans2 *= (LL)bcc[i].size() - ;
}
}
if (bcc_cnt == )
{
ans1 = ;
ans2 *= (LL)bcc[].size() * (bcc[].size() - ) / ;
}
cout << "Case " << ++iCase << ": " << ans1 << " " << ans2 << endl;
}
return ;
}
UVALive - 5135 - Mining Your Own Business(双连通分量+思维)的更多相关文章
- UVALive 5135 Mining Your Own Business 双连通分量 2011final
题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱, ...
- UVALive 5135 Mining Your Own Business 双连通分量
据说这是一道Word Final的题,Orz... 原题链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&a ...
- UVALive - 5135 Mining Your Own Business
刘汝佳白书上面的一道题目:题意是给定一个联通分量,求出割顶以及双连通分量的个数,并且要求出安放安全井的种类数,也就是每个双连通分量中结点数(除开 割顶)个数相乘,对于有2个及以上割顶的双连通分量可以不 ...
- LA 5135 井下矿工(点—双连通分量模板题)
https://vjudge.net/problem/UVALive-5135 题意:在一个无向图上选择尽量少的点涂黑,使得任意删除一个点后,每个连通分量至少有一个黑点. 思路: 首先dfs遍历求出割 ...
- 【LA】5135 Mining Your Own Business
[算法]点双连通分量 [题解]详见<算法竞赛入门竞赛入门经典训练指南>P318-319 细节在代码中用important标注. #include<cstdio> #includ ...
- UVALive 5135 Mining Your Own Bussiness【tarjan点双】
LINK1 LINK2 题目大意 给你一个无向连通图,让你给一些点染上黑色,需要满足染色之后,断开任意一个节点,要满足任意一个联通块中剩下的节点中至少有一个黑点 思路 一开始想的是把每一个点双联通分量 ...
- LA 5135 Mining Your Own Business
求出 bcc 后再……根据大白书上的思路即可. 然后我用的是自定义的 stack 类模板: #include<cstdio> #include<cstring> #includ ...
- 训练指南 UVALive - 5135 (双连通分量)
layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...
- hdu3844 Mining Your Own Business,无向双连接组件
点击打开链接 无向图的双连通分量 #include<cstdio> #include<stack> #include<vector> #include<map ...
随机推荐
- .netcore使用SocketAsyncEventArgs Pool需要注意!
在.net中做网络通讯往往都会用到SocketAsyncEventArgs,为了得到更好的性能配合Pool复用SocketAsyncEventArgs可以得到一个更好的效果,但在dotnet core ...
- leetcode — binary-tree-inorder-traversal
import java.util.Arrays; import java.util.Stack; import java.util.TreeMap; /** * * Source : https:// ...
- leetcode — restore-ip-addresses
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util. ...
- 导航页-LeetCode专题-Python实现
LeetCode专题-Python实现之第1题:Two Sum LeetCode专题-Python实现之第7题:Reverse Integer LeetCode专题-Python实现之第9题:Pali ...
- Docker多主机管理(八)--技术流ken
docker多主机管理 前面我们的实验环境中只有一个 docker host,所有的容器都是运行在这一个 host 上的.但在真正的环境中会有多个 host,容器在这些 host 中启动.运行.停止和 ...
- C#程序员知识体系
[https://blog.csdn.net/zj735539703/article/details/50409476] 基础部分 C# 基础语法 OOP的概念,面向对象的理解 继承 封装 多态 AS ...
- [转]在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
本文转自:https://www.cnblogs.com/kongxianghai/p/5582661.html Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用Ja ...
- 我的第三个开源库GuaJiangViewDemo——中文文档
GuaJiangViewDemo 欢迎Star 一个可以简单的刮刮奖View的封装 测试图 使用 1.在根目录上添加 maven { url 'https://jitpack.io' } 2.添加依赖 ...
- C#面试分享:单例模式
C#面试分享:单例模式 提问1:请给出单例模式的实现: 答: public class Animal { private static Animal _instance = null; private ...
- 小程序多端框架全面测评:chameleon、Taro、uni-app、mpvue、WePY
摘要: 微信小程序开发技巧. 作者:coldsnap 原文:小程序多端框架全面测评 Fundebug经授权转载,版权归原作者所有. 最近前端届多端框架频出,相信很多有代码多端运行需求的开发者都会产生一 ...