[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 ...
随机推荐
- SAP 日志管理
现在项目上自开发的dialog程序越来越多,有很多敏感数据需要像SAP标准的业务一样,能看到所有的修改日志,要想实现日志的功能,有以下几个办法: 办法一.建一个日志表,在原有表的基础上,加上日期和时间 ...
- JZOJ 100029. 【NOIP2017提高A组模拟7.8】陪审团
100029. [NOIP2017提高A组模拟7.8]陪审团 Time Limits: 1000 ms Memory Limits: 131072 KB Detailed Limits Got ...
- Lake Counting(dfs)
Description Due to recent rains, water has pooled in various places in Farmer John's field, which is ...
- Watchmen CodeForces - 650A
Watchmen CodeForces - 650A Watchmen are in a danger and Doctor Manhattan together with his friend Da ...
- 团体程序设计天梯赛-练习集 L2-001 紧急救援 (25 分)
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...
- 新手用WPF山寨QQ管家7.6(三)
由于一直忙工作,没有更新完博客,更可恨的是...在清理资料的时候不小心删除了之前自己做的各种效果的DEMO....好在项目中用到了大部分,也算有所保留,以后可不敢随便删东西了....太可怕了! 在 新 ...
- 【Reverse Linked List II】cpp
题目: Reverse a linked list from position m to n. Do it in-place and in one-pass. For example:Given 1- ...
- Effictive C++ 学习记录
这是前段时间看的书,整理到这里吧,以后查看也方便. 这些条款需要反复查看. 条款01:视C++为一个语言联邦 条款02:尽量用const.enum.inline替换#define 条款03:尽可能的使 ...
- Mybatis使用- Mybatis JdbcType与Oracle、MySql数据类型对应列表 ; Mybatis中javaType和jdbcType对应关系
Mybatis JdbcType与Oracle.MySql数据类型对应列表 Mybatis JdbcType Oracle MySql JdbcType ARRAY JdbcType BIG ...
- Monkey官方帮助翻译&介绍
都说想学好就看原文,英文不好为了翻译这个可费了大劲了.表格从GOOGLE官网复制到WORD里编辑,结果贴上来格式全乱了,只得不弄表格了.表格中官网的事件不是最新的,比最新的少2个,具体我会另发一篇文章 ...