[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 ...
随机推荐
- js中的||、&&与!用法
&&和||在JQuery源代码内尤为使用广泛,由网上找了些例子作为参考,对其用法研究了一下: 1. && function a(){ alert("a&quo ...
- Oracle10g安装过程中的Configuration Assistant配置失败的问题。
前几天安装Oracle的时候碰到了一个小问题,是在最后配置的时候,出现失败提示如下 失败提示:一些 Configuration Assistant 失败.强烈建议您此时重试这些 Configurati ...
- Linux系统故障分析与排查--日志分析
处理Linux系统出现的各种故障时,故障的症状是最先发现的,而导致这以故障的原因才是最终排除故障的关键.熟悉Linux系统的日志管理,了解常见故障的分析与解决办法,将有助于管理员快速定位故障点,“对症 ...
- Linux 下上传下载命令,SCP,SFTP,FTP
scp 帮助命令: man scp scp功能: 下载远程文件或者目录到本地, 如果想上传或者想下载目录,最好的办法是采用tar压缩一下,是最明智的选择. 从远程主机 下载东西到 本地电脑 拷贝文件命 ...
- 两台centos之间使用scp命令传输文件
1.将本地文件copy到远程 (1)复制文件 scp local_file remote_username@remote_ip:remote_folder 例如:将/usr/local/aa.png文 ...
- 整合mybatis和spring时 Error creating bean with name 'sqlSessionFactory' defined in class path resource
今天在整合mybatis和spring的时候出的错 报错如下 Exception in thread "main" org.springframework.beans.factor ...
- 用jq给img添加error事件
<img src="xxxx.jpg" alt="" /> <script> $(document).ready(function(){ ...
- 使用cxf 发布 jax-rs 风格webservice 。并客户端测试。
详细介绍:http://www.ibm.com/developerworks/cn/java/j-lo-jaxrs/ 1.定义一个User对象 package com.zf.test; import ...
- 谭浩强C第四版(p141)16.输出以下图案
运行结果: * *** ***** ******* ***** *** * Press any key to continue #include<stdio.h> int main() { ...
- L1-039 古风排版 (20 分)
L1-039 古风排版 (20 分) 中国的古人写文字,是从右向左竖向排版的.本题就请你编写程序,把一段文字按古风排版. 输入格式: 输入在第一行给出一个正整数N(<),是每一列的字符数.第 ...