[HNOI2012]矿场搭建(tarjan求点双)
题目
Description
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
Input
输入文件有若干组数据,每组数据的第一行是一个正整数 N,表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T ,表示挖煤点 S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。
Output
输入文件中有多少组数据,输出文件中就有多少行。每行对应一组输入数据的结果。
其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与 : 之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i组输入数据至少需要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总数。
输出格式参照以下输入输出样例。
题解
再点双连通分量中,如果坏了其中一个点,那么剩下的点还是连通的,所以我们求一次点双连通分量,再仔细观察一下,如果一个点双中(非割点点数为 \(n\)):
- 没有割点,那么显然要两个通道,共 \(C_n^2\) 种选法。
- 有一个割点,那么在这个点双中就要有一个通道,共,有一个割点,那么在这个点双中就要有一个通道,共 \(n\) 种选法。
- 有两个或者两个以上的割点,则不需要通道。
问题解决了,不过我可能是太弱了,统计割点数和非割点数写挂了,我们其实可以把每个割点找出来,dfs 一遍,割点之间就是一个点双,另外相邻的割点也属于这个点双。
CODE
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
using namespace std;
int dfn[10005],low[10005],cp[10005],cnt=0;
int bcc[10005],num[10005],son[10005],C=0;
bool vis[100005],iscp[100005];
int n,m,x,y,h[100005],tot=0,cas=0;
struct Edge{
int x,next;
}e[200005];
inline void add_edge(int x,int y){
e[++tot].x=y;
e[tot].next=h[x],h[x]=tot;
}
stack<int> s;
void tarjan(int x,int fa){
low[x]=dfn[x]=++cnt;
son[x]=0;
for(int i=h[x];i;i=e[i].next){
if(e[i].x==fa)continue;
if(!dfn[e[i].x]){
tarjan(e[i].x,x),son[x]++;
low[x]=min(low[x],low[e[i].x]);
if(low[e[i].x]>=dfn[x]&&fa!=0)iscp[x]=true;
}
else low[x]=min(low[x],dfn[e[i].x]);
}
if(son[x]>1&&fa==0)iscp[x]=true;
}
void dfs(int x){
vis[x]=true,num[C]++;
for(int i=h[x];i;i=e[i].next){
if(vis[e[i].x])continue;
if(!iscp[e[i].x])dfs(e[i].x);
else{
if(bcc[e[i].x]!=C)
bcc[e[i].x]=C,cp[C]++;
}
}
}
int main(){
while(scanf("%d",&m),m){
memset(h,0,sizeof(h));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(bcc,0,sizeof(bcc));
memset(num,0,sizeof(num));
memset(cp,0,sizeof(cp));
memset(iscp,0,sizeof(iscp));
memset(vis,0,sizeof(vis));
tot=cnt=C=n=0;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
n=max(n,max(x,y));
}
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i,0);
unsigned long long sum=0,ans=1;
for(int i=1;i<=n;i++){
if(!iscp[i]&&!vis[i]){
C++,dfs(i);
if(cp[C]==1)sum++,ans*=num[C];
}
}
if(C==1)sum=2,ans=n*(n-1)/2;
printf("Case %d: ",++cas);
printf("%llu %llu\n",sum,ans);
}
}
[HNOI2012]矿场搭建(tarjan求点双)的更多相关文章
- bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双
Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...
- BZOJ 2730: [HNOI2012]矿场搭建( tarjan )
先tarjan求出割点.. 割点把图分成了几个双连通分量..只需dfs找出即可. 然后一个bcc有>2个割点, 那么这个bcc就不用建了, 因为一定可以走到其他救援出口. 只有一个割点的bcc就 ...
- 【BZOJ2730】[HNOI2012]矿场搭建 Tarjan
[BZOJ2730][HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处. ...
- BZOJ 2730 矿场搭建 Tarjan求割点
思路: Tarjan求出来点双&割点 判一判就行了 //By SiriusRen #include <stack> #include <cstdio> #include ...
- BZOJ2730 [HNOI2012]矿场搭建 - Tarjan割点
Solution 输入中没有出现过的矿场点是不用考虑的, 所以不用考虑只有 一个点 的点双联通分量. 要使某个挖矿点倒塌, 相当于割去这个点, 所以我们求一遍割点和点双联通分量. 之后的点双联通分量构 ...
- P3225 [HNOI2012]矿场搭建 tarjan割点
这个题需要发现一点规律,就是先按割点求块,然后求每个联通块中有几个割点,假如没有割点,则需要建两个出口,如果一个割点,则需要建一个出口,2个以上不用建. 题干: 题目描述 煤矿工地可以看成是由隧道连接 ...
- [BZOJ2730][HNOI2012]矿场搭建(求割点)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2730 分析: 如果坍塌的点不是割点,那没什么影响,主要考虑坍塌的点是割点的情况. 显然 ...
- C++[Tarjan求点双连通分量,割点][HNOI2012]矿场搭建
最近在学图论相关的内容,阅读这篇博客的前提是你已经基本了解了Tarjan求点双. 由割点的定义(删去这个点就可使这个图不连通)我们可以知道,坍塌的挖煤点只有在割点上才会使这个图不连通,而除了割点的其他 ...
- Tarjan 点双+割点+DFS【洛谷P3225】 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 【BZOJ-2730】矿场搭建 Tarjan 双连通分量
2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1602 Solved: 751[Submit][Statu ...
随机推荐
- 1005: [HNOI2008]明明的烦恼
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6539 Solved: 2558[Submit][Status][Discuss] Descripti ...
- BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)
题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...
- dynamic routing between captual
对于人脑 决策树形式 对于CNN 层级与层级间的传递 人在识别物体的时候会进行坐标框架的设置 CNN无法识别,只能通过大量训练 胶囊 :一个神经元集合,有一个活动的向量,来表示物体的各类信息,向量的长 ...
- LeetCode949-给定数字能组成的最大时间
问题: 给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间. 最小的 24 小时制时间是 00:00,而最大的是 23:59.从 00:00 (午夜)开始算起,过得越久,时间 ...
- ZendFramework-2.4 源代码 - ViewManager类图
- 初级React入门
一.引入Reactjs 方法一:直接下载相关js文件引入网页,其中react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 ...
- STM32串口中断实例二
int main(void) { uint8_t a=;//LED高低电压控制 /* System Clocks Configuration */ RCC_Configuration(); //系统时 ...
- Gym - 101128F Landscaping(网络流)
题意 给你一个\(N×M\)的草地,有高地有低地. 收割机从低地走到高地或者从高地走到低地都要花费用\(A\),你可以花费用\(B\)把一块高地变成低地,或者把一块低地变成高地.收割机每行每列都是必须 ...
- thinkpad alert键一直处于按着的状态
就是alert 一直默认按着的,具体原因,我还没有见过. 但是解决方法很简单,crlt+alert一块按,就好了.
- React基础(Diff算法,属性和状态)
1.React的背景原理 (1)React Diff算法流程 (2)React虚拟DOM机制 React引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DO ...