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 题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条 ...
随机推荐
- Spring AOP基于注解的“零配置”方式实现
为了在Spring中启动@AspectJ支持,需要在类加载路径下新增两个AspectJ库:aspectjweaver.jar和aspectjrt.jar.除此之外,Spring AOP还需要依赖一个a ...
- ubuntu14.10下Qt5.4无法输入中文
最近学习Qt,于是在ubuntu下安装了开发环境.我是从官网上下载安装的Qt5.4版本.安装后发现在开发过程中无法输入中文.于是在网上搜了搜.解决办法如下: 1.安装fcitx-frontend-qt ...
- 【285】ArcPy 暗色窗体设置
预览图 设置如下 Default:
- SonarQube在CentOS上的安装
1 简介 SonarQube 是一个用于代码质量管理的开放平台.通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具.与持续集成工具(例如 Hudson/Jenkins 等 ...
- ZigBee协议栈中AES加密算法
原文地址:ZigBee协议栈中AES加密算法作者:大浪淘沙 Z-stack对Zigbee2006提供了全面的支持,功能之强大,性能稳定.安全性高,说到安全性是我们今天的主题.CC2430硬件支持128 ...
- 【原】Coursera—Andrew Ng机器学习—编程作业 Programming Exercise 1 线性回归
作业说明 Exercise 1,Week 2,使用Octave实现线性回归模型.数据集 ex1data1.txt ,ex1data2.txt 单变量线性回归必须实现,实现代价函数计算Computin ...
- Docker镜像加速 | Docker 中国源 | 仓库
镜像加速 | Docker 中国https://www.docker-cn.com/registry-mirror
- Codeforces 1142D Foreigner (DP)
题意:首先定义了一种类数(标志数) 1:1到9都是标志数. 2:若x / 10是标志数,假设x /10在标志数中的排名是k, 若x的个位数小于k % 11, 那么x也是标志数. 现在给你一个字符串,问 ...
- Linux问题:开启网关
1 开启网关 1.1 问题描述 虚拟机每次重启后,都需要利用 ifup eth0 来手动开启网关,否则获取到的IP地址为回环127.0.0.1 1.2 解决办法 修改ifcfg-eth0中 ONBOO ...
- Django框架 之 Ajax
Django框架 之 Ajax 浏览目录 AJAX准备知识 AJAX与XML的比较 AJAX简介 jQuery实现的ajax AJAX参数 AJAX请求如何设置csrf_token 序列化 一.AJA ...