Tarjan 点双+割点+DFS【洛谷P3225】 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建
题目描述
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
点双入门。。。 话说题意是真的晦涩。
一眼求割点,求完割点怎么办?
因为我们把割点去掉之后,图中会剩下一个一个的块,这些块就是点双。
那么限制工人逃跑的就是割点,所以我们在乎的是每个点双中有多少个割点。
那么我们就可以通过Tarjan给所有割点打上一个标记。
然后再去DFS出所有的点双,这个过程需要记录点双中的点和点双中的割点数。有些细节。
然后就可以愉快地分情况讨论了。
(一),当前点双内没有割点,那么这个点双是独立的也就是不和其他的块联通,那么对于这个点双内的点我们就需要建立两个救援出口,为什么呢,因为有一个炸了还有另外一个。所以\(ans1+=2\)
然后方案数通过乘法原理和组合数搞一搞就行了,也就是\(ans2*=C(tot,2)\)。
(二),当前点双内只有一个割点,那么可以知道如果这个割点炸了我们就翻车了,所以我们可以继承(一)的思想,只是把这个已有的割点看成一个必然的出口,所以我们还需要建1个出口,方案数为\(ans2*=C(tot,1)\)。
(三),当前点双内有两个割点,还是一样的思想,就会发现我们不用再建出口了,因为可以把两个割点看成两个出口,任意一个炸了我们还有另一个。
ok,那就可以开始愉快地写代码了喵喵喵。。。
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define int long long
const int wx=517;
inline int read(){
int sum=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
return sum*f;
}
int n,m,ans1,ans2,num,sjc,tot,zmj,cnt;
int dfn[wx],head[wx],ok[wx],vis[wx],low[wx];
struct e{
int nxt,to;
}edge[wx*2];
void add(int from,int to){
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
}
void Tarjan(int u,int f){
dfn[u]=low[u]=++tot; int child=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==f)continue;
if(!dfn[v]){
Tarjan(v,u);
child++;
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])ok[u]=1;
}
else if(dfn[v]<dfn[u]&&v!=f){
low[u]=min(low[u],dfn[v]);
}
}
if(child<=1&&f==-1)ok[u]=0;
}
void dfs(int u){
vis[u]=tot; zmj++;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(vis[v]!=vis[u]&&ok[v])cnt++,vis[v]=tot;
if(!vis[v]&&!ok[v])dfs(v);
}
}
void clear(){
num=0,tot=0;
memset(head,0,sizeof head);
memset(edge,0,sizeof edge);
memset(vis,0,sizeof vis);
memset(dfn,0,sizeof dfn);
memset(ok,0,sizeof ok);
}
signed main(){
while(1){
m=read(); if(!m)break;
n=0; sjc++; ans1=0; ans2=1;
clear();
for(int i=1;i<=m;i++){
int x,y;
x=read(); y=read();
add(x,y); add(y,x); n=max(n,max(x,y));
}
for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,-1);
for(int i=1;i<=n;i++){
if(ok[i]||vis[i])continue;
tot++; zmj=0,cnt=0; dfs(i);
if(cnt==0)ans1+=2,ans2*=(zmj-1)*zmj/2;
if(cnt==1)ans1++,ans2*=zmj;
}
printf("Case %lld: %lld %lld\n",sjc,ans1,ans2);
}
return 0;
}
Tarjan 点双+割点+DFS【洛谷P3225】 [HNOI2012]矿场搭建的更多相关文章
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 洛谷——P3225 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 洛谷P3225 HNOI2012 矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
- 洛谷—— P3225 [HNOI2012]矿场搭建
https://www.luogu.org/problem/show?pid=3225 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有 ...
- 洛谷 P3225 [HNOI2012]矿场搭建
传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...
- BZOJ2730或洛谷3225 [HNOI2012]矿场搭建
BZOJ原题链接 洛谷原题链接 显然在一个点双连通分量里,无论是哪一个挖煤点倒塌,其余挖煤点就可以互相到达,而对于一个点双连通分量来说,与外界的联系全看割点,所以我们先用\(tarjan\)求出点双连 ...
- [Luogu] P3225 [HNOI2012]矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
- P3225 [HNOI2012]矿场搭建
传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...
- P3225 [HNOI2012]矿场搭建 割点 tarjan 双联通分量
https://www.luogu.org/problemnew/show/P3225 题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条 ...
随机推荐
- mysql之提示符
MySQL常用的简单的命令: mysql> PROMPT \u@\h \d> PROMPT set to '\u@\h \d>' root (none)>USE test Da ...
- Linux的基本指令shell
计算机语言的进化过程,7代语言 机器语言(6种位运算)-> 汇编语言->C语言 -> C++/Java -> Paython / go /Ruby -> 自 ...
- tmux颜色高亮跟vim不一致的情况
安装完tmux之后,按照网上大神的配置,稍微配置了下~/.tmux.conf: # 改变快捷键前缀 unbind C-b set -g prefix C-a # 绑定配置加载按键 bind r sou ...
- .net中动态对象的使用
js中的写法: var list = []; var o = {}; o.id = '111'; o.name = '222'; list.push(o); c#中的写法: var aList = n ...
- opennebula 一些问t题讨论
ou_ian - June 8th, 2011 11:13 am非常想请教一下如何设置VM的ip为DHCP? 我们的VM都需要通过eth0 (通过公司的DHCP获得ip)来连接到公司的网络(Inter ...
- PHP数组的详细解读
数组的定义 数组的本质是管理和操作一组变量,数组中可以存储任意长度的数据,也可以存储任意类型的数据.数组中的单元称为元素,每个元素包括下标(键)和值,访问元素的时候,是通过下标来访问,包括一维数组,二 ...
- launchpad, jira, github
一.简介 http://segmentfault.com/q/1010000000165115
- list 的扩展
数据挖掘中会遇到添加多个新的特征s,对一个feature = list()来说, 除了可以用 feature.append('xx') # 在尾部添加一个特征 feature.extend(['xx' ...
- redirect_uri域名与后台配置不一致,错误码:10003
登录公众平台,重新配置下网页授权域名就可以了 参考https://blog.csdn.net/haoxuexiaolang/article/details/79432073
- pymysql模块使用---Python连接MySQL数据库
pymysql模块使用---Python连接MySQL数据库 浏览目录 pymysql介绍 连接数据库 execute( ) 之 sql 注入 增删改查操作 进阶用法 一.pymysql介绍 1.介绍 ...