[Luogu] P3225 [HNOI2012]矿场搭建
题目描述
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
题目解析
tarjan找双联通分量,找割点。
在一个分量里有 ≥2 个割点,这个分量就怎么都能跑出去,不需要建出口。
在一个分量里有 1 个割点,这个分量就要防止割点塌了,需要建1个出口。
在一个分量里没有割点,说明它不和别的分量连通,为了防止出口塌掉,要建两个出口。
看起来有些坑,值得注意的是,一个点只会在一个强连通分量,但可能同时处于多个双联通分量
Code
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int MAXN = + ; struct Edge {
int nxt;
int to;
} l[MAXN<<]; int n,m,res,T;
int tot,stamp;
int head[MAXN],cnt;
int low[MAXN],dfn[MAXN];
int sum,num;
int root,deg;
int vis[MAXN],col[MAXN];
bool cut[MAXN];
long long ans1,ans2 = ; void tarjan(int x,int from) {
dfn[x] = low[x] = ++stamp;
for(int i = head[x];i;i = l[i].nxt) {
if(!dfn[l[i].to]) {
tarjan(l[i].to,x);
low[x] = min(low[x],low[l[i].to]);
if(low[l[i].to] >= dfn[x]) {
if(x == root) deg++;
else cut[x] = true;
}
} else if(l[i].to != from) low[x] = min(low[x],dfn[l[i].to]);
}
return;
} void dfs(int x) {
vis[x] = tot;
if(cut[x]) return;
sum++;
for(int i = head[x];i;i = l[i].nxt) {
if(cut[l[i].to] && vis[l[i].to] != tot) num++,vis[l[i].to] = tot;
if(!vis[l[i].to]) dfs(l[i].to);
}
} inline void add(int x,int y) {
cnt++;
l[cnt].nxt = head[x];
l[cnt].to = y;
head[x] = cnt;
return;
} inline void clean() {
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(head,,sizeof(head));
memset(col,,sizeof(col));
memset(cut,,sizeof(cut));
memset(vis,,sizeof(vis));
num = sum = ;
ans1 = n = tot = stamp = cnt = ;
ans2 = ;
} int main() {
while(~scanf("%d",&m) && m) {
clean();
int x,y;
for(int i = ;i <= m;i++) {
scanf("%d%d",&x,&y);
n = max(n,max(x,y));
add(x,y),add(y,x);
}
for(int i = ;i <= n;i++) {
if(!dfn[i]) {
deg = ;
tarjan(root = i,);
if(deg >= ) cut[root] = true;
}
}
for(int i = ;i <= n;i++) {
if(!vis[i] && !cut[i]) {
tot++;
sum = num = ;
dfs(i);
if(!num && sum > ) ans1 += , ans2 *= sum*(sum-)/;
else if(num == ) ans1++, ans2 *= sum;
}
}
printf("Case %d: %lld %lld\n",++T,ans1,ans2);
}
return ;
}
[Luogu] P3225 [HNOI2012]矿场搭建的更多相关文章
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 洛谷——P3225 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- P3225 [HNOI2012]矿场搭建 割点 tarjan 双联通分量
https://www.luogu.org/problemnew/show/P3225 题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条 ...
- P3225 [HNOI2012]矿场搭建 题解
这道题挺难的,可以加深对割点的理解,还有,排列组合好重要了,分连通块,然后乘法原理(加法原理计数什么的) 传送门 https://www.luogu.org/problem/P3225 省选oi题 ...
- 洛谷—— P3225 [HNOI2012]矿场搭建
https://www.luogu.org/problem/show?pid=3225 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有 ...
- 洛谷P3225 HNOI2012 矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
- 洛谷 P3225 [HNOI2012]矿场搭建
传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...
- P3225 [HNOI2012]矿场搭建
传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...
- P3225 [HNOI2012]矿场搭建 tarjan割点
这个题需要发现一点规律,就是先按割点求块,然后求每个联通块中有几个割点,假如没有割点,则需要建两个出口,如果一个割点,则需要建一个出口,2个以上不用建. 题干: 题目描述 煤矿工地可以看成是由隧道连接 ...
随机推荐
- 【OI】Kruskal & ufs (克鲁斯卡与并查集)
Kruskal是有关于最小生成树的算法. 这个算法非常好理解,用一句话来概括就是: 从小到大找不同集合的边. 那么,具体是怎样的呢. 1.先把所有顶点初始化为一个连通分量. 2.从所有边中选择最小的( ...
- Bootstrap 模态窗口源码分析
前言: bootstrap的 js插件的源码写的非常好,也算是编写jquery插件的模范写法,本来还想大篇详细的分析一下呢,唉,没时间啊,很早之前看过的源码了,现在贴在了博客上, 300来行的代码,其 ...
- 【Silverlight】Bing Maps学习系列(一):开发前的准备工作
[Silverlight]Bing Maps学习系列(一):开发前的准备工作 微软推出的Bing Maps地图引擎,对外开放了Silverlight和Ajax两种客户端API,同时微软针对全球地图还推 ...
- Eclipse 工程配置与目录结构及各种文件夹(常用插件)
.classpath..project 是 Eclipse 工程所必须的文件. OpenExplorer: 该 jar 包的下载地址:samsonw/OpenExplorer 安装配置方法:eclip ...
- PyCharm创建文件时自动添加头文件
依次找到以下路径: File->settings->Editor->File and Code Templates->Python Script #!/usr/bin/env ...
- TI BLE: Advertisement
#define GAPROLE_ADVERT_ENABLED 0x305 //!< Enable/Disable Advertising. Read/Write. Size is uint8. ...
- 15_传智播客iOS视频教程_OC语言完全兼容C语言
OC支持C语言所有的运算符并且效果是一样的.C语言中所有的运算符OC都支持.这些所有的运算符OC当中全部都支持. 包括C语言的结构体.枚举全部都可以写在OC当中,没有任何问题,并且效果是一样的. 比如 ...
- 符号修饰与函数签名、extern “C”(转载)
转自:http://www.cnblogs.com/monotone/archive/2012/11/16/2773772.html 参考资料: <程序员的自我修养>3.5.3以及3.5. ...
- Linux学习笔记之Linux相关知识
[想成为某一方面的大神,没有捷径可走,只能不断的记录.练习.总结.coding……] notes:主要从网上摘录了一些关于Linux的历史以及一些相关内容,以便对Linux系统有一定的了解.这不但可以 ...
- fread/fwrite实现复制功能
1. fread/fwrite实现复制功能 #include <stdio.h> #include <stdlib.h> #define BUFFSIZE 4096 //执行 ...