博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 2730: [HNOI2012]矿场搭建
阅读量:5052 次
发布时间:2019-06-12

本文共 2852 字,大约阅读时间需要 9 分钟。

Description

煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

Input

输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖       S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。

Output

输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。

Sample Input

9
1 3
4 1
3 5
1 2
2 6
1 5
6 3
1 6
3 2
6
1 2
1 3
2 4
2 5
3 6
3 7
0

Sample Output

Case 1: 2 4
Case 2: 4 1

HINT

Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);
Case 2 的一组解为(4,5,6,7)。

Source

 

HNOI蒯白书原题啊...

 

本题的模型是:在无向图上选择尽量少的点涂黑,使得任意删除一个点后,每个连通分量至少有一个黑点.

看到这种题首先就进行点双连通分量的缩点(因为是删点),然后这就是一棵树,且树上的节点是以割点为交集...

 

对于叶子节点(即只有一个割点),则该连通分量必须建一个,不然与爸爸的割点爆掉后就gi了

(如果自己里面的爆掉,该点双内所有点都可通过与爸爸的割点往外跑,跑到另一个叶子节点就可以了)

 

对于非叶子节点,就不用建,爆了和爸爸的还可以往儿子那里跑,跑到叶子节点就安全了

 

特判如果没有割点的话(就是只有一个叶子节点,靠不了谁),就需要任选两个建

点双连通分量的实现的话,先把割点找出来,然后不走割点即可(但割点是括在点双连通分量内的)

#include
#include
#include
#include
#include
using namespace std;typedef long long ll;const int N=100050;int gi(){ int x=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*flag;}int head[N],nxt[N],to[N],dfn[N],low[N],pd[N],tt,tong[N],cnt,tot,check[N],vis[N],vis2[N],size[N];unsigned long long ans1,ans2;void tarjan(int x,int rt){ dfn[x]=low[x]=++tt;int flag=0; for(int i=head[x];i;i=nxt[i]){ int y=to[i]; if(!dfn[y]){ tarjan(y,rt); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]) flag++; } else low[x]=min(dfn[y],low[x]); } if(x!=rt&&flag) pd[x]=1; if(x==rt&&flag>1) pd[x]=1;}void dfs(int x,int frr){ vis[x]=1,size[frr]++; for(int i=head[x];i;i=nxt[i]){ int y=to[i]; if(!vis[y]&&pd[y]==0) dfs(y,frr); else if(pd[y]==1&&vis2[y]!=frr) check[frr]++,vis2[y]=frr; }}void lnk(int x,int y){ to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt; to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;}int main(){ int T=0; while(1){ int n,x,y;T++;n=gi(); if(n==0) return 0;int num=0; ans1=0,ans2=1,tt=0,tot=0,cnt=1; for(int i=1;i<=n;i++){ int x=gi(),y=gi(); if(!tong[x]) num++,tong[x]++; if(!tong[y]) num++,tong[y]++; lnk(x,y); } for(int i=1;i<=num;i++) if(!dfn[i]) tarjan(i,i); for(int i=1;i<=num;i++) if(!vis[i]&&pd[i]==0) dfs(i,++tot); for(int i=1;i<=tot;i++){ if(check[i]==0) ans1+=2,ans2*=(size[i]-1)*(size[i])/2; else if(check[i]==1) ans1++,ans2*=size[i]; } for(int i=1;i<=num;i++) head[i]=size[i]=check[i]=pd[i]=dfn[i]=low[i]=tong[i]=vis[i]=vis2[i]=0; cout<<"Case "<
<<":"<<' '<
<<' '<
<

 

转载于:https://www.cnblogs.com/qt666/p/6880504.html

你可能感兴趣的文章
Win8 安装VS2012 和 Sql Server失败问题
查看>>
过点(2,4)作一直线在第一象限与两轴围成三角形,问三角形面积的最小值?...
查看>>
java aes CBC的填充方式发现
查看>>
使用ionic cordova build android --release --prod命令打包报有如下错误及解决方法
查看>>
BZOJ 2338 HNOI2011 数矩形 计算几何
查看>>
关于页面<!DOCTYPE>声明
查看>>
【AS3代码】播放FLV视频流的三步骤!
查看>>
C++标准库vector使用(更新中...)
查看>>
cocos2d-x 2.2.6 之 .xml文件数据读取
查看>>
枚举的使用
查看>>
BZOJ 1531 二进制优化多重背包
查看>>
BZOJ 2324 (有上下界的)费用流
查看>>
python3基础06(随机数的使用)
查看>>
Zookeeper系列(二)特征及应用场景
查看>>
【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试
查看>>
Spring Boot使用Druid和监控配置
查看>>
poi 处理空单元格
查看>>
Android 内存泄漏优化总结
查看>>
luogu4849 寻找宝藏 (cdq分治+dp)
查看>>
Spring Cloud微服务笔记(五)Feign
查看>>