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 ...
随机推荐
- 翻译 异步I/O不会创建新的线程
异步I/O不会创建新的线程 本文翻译自 Stephen Cleary 的 [There is No Thread] 原文地址 https://blog.stephencleary.com/2013/1 ...
- [十]JavaIO之FilterInputStream FilterOutputStream
FilterInputStream FilterOutputStream都是装饰器模式中的Decorator抽象装饰角色 他们继承了各自的抽象构建InputStream 和OutputStream ...
- 语音识别(LSTM+CTC)
完整版请微信关注“大数据技术宅” 序言:语音识别作为人工智能领域重要研究方向,近几年发展迅猛,其中RNN的贡献尤为突出.RNN设计的目的就是让神经网络可以处理序列化的数据.本文笔者将陪同小伙伴们一块儿 ...
- JavaScript 条件语句
if语句 有些代码块只能在一定条件下运行,通过if.if else.else代码块,可以让你的代码按条件执行. // 控制流 var foo = true; var bar = false; ...
- Java集合类源码解析:AbstractList
今天学习Java集合类中的一个抽象类,AbstractList. 初识AbstractList AbstractList 是一个抽象类,实现了List<E>接口,是隶属于Java集合框架中 ...
- mysql修改连接数
方法一: 进入MySQL安装目录 打开MySQL配置文件 my.ini 或 my.cnf查找 max_connections=100 修改为 max_connections=1000 服务里重起M ...
- Linux平台安装MongoDB及使用Docker安装MongoDB
一.Linux平台安装MongoDB MongoDB 提供了 linux 各发行版本 64 位的安装包,你可以在官网下载安装包. 下载地址:https://www.mongodb.com/downlo ...
- 我从来不理解JavaScript闭包,直到有人这样向我解释它...
摘要: 理解JS闭包. 原文:我从来不理解JavaScript闭包,直到有人这样向我解释它... 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 正如标题所述,JavaScript闭包 ...
- BIM与GIS
BIM行业是建筑与IT结合而形成的一个新兴行业,既然能说是行业,说明它包含的内容非常丰富,懂一点和完全懂是两码事,就好像一滴水和一片大海的范围一样.现在国内有很多高校开设了BIM专业,并对口招收了学生 ...
- 让自定义view宽高成比例显示
有时候我们自定义一个View,比如ImageView,我们需要让它宽高按照一定的比例显示,例如在ImageView在GridView中显示,GridView设置了3列,由于ImageVIew的宽度会根 ...