[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个以上不用建. 题干: 题目描述 煤矿工地可以看成是由隧道连接 ...
随机推荐
- HDU 4850 Wow! Such String!(欧拉道路)
HDU 4850 Wow! Such String! 题目链接 题意:求50W内的字符串.要求长度大于等于4的子串,仅仅出现一次 思路:须要推理.考虑4个字母的字符串,一共同拥有26^4种,这些由这些 ...
- luogu 3388 【模板】割点(割顶)
点双. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> ...
- luogu 1083 借教室
题目大意: 有一些教室 我们需要处理接下来n天的借教室信息 其中第i天学校有ri个教室可供租借 共有m份订单 每份订单用三个正整数描述 分别为dj sj tj 表示从第sj天到第tj天租借教室 每天需 ...
- 洛谷 P1351 联合权值 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...
- 洛谷 P3960 [ NOIP 2017 ] 列队 —— 线段树
题目:https://www.luogu.org/problemnew/show/P3960 NOIP 题,不用很复杂的数据结构...但又参考了许多: 要求支持维护删除第 k 个和在末尾插入的数据结构 ...
- bzoj 1704: [Usaco2007 Mar]Face The Right Way 自动转身机【贪心+差分】
首先O(n^3)的贪心很好想,就是枚举k然后从前往后扫,扫到反就翻转区间 然后考虑优化掉翻转区间维,就是搞成差分的形式,在翻转区间的尾部打上标记,再用一个变量维护当前的翻转次数,加到当前状态上来判断是 ...
- linux vi 块操作、多窗口
vim 块选择v:字符选择或者行选择[ctrl]+v: 块选择y:将反白的地方复制d:将反白的地方删除 多窗口:sp {filename} 打开一个新的窗口[ctrl]+w+j或者[ctrl]+w+向 ...
- jQuery图片区域选择控件_imgAreaSelect
软考报名时发现可以进行头像区域裁剪功能,F12了一下,发现使用了imgAreaSelect控件. 控件官网: http://odyniec.net/projects/imgareaselect/ 控件 ...
- DHTML_____window对象属性
<html> <head> <meta charset="utf-8"> <title>window对象属性</title&g ...
- Linux用户、用户组权限管理详解
Linux用户管理三个重要文件详解: Linux登陆需要用户名.密码./etc/passwd 文件保存用户名.登录Linux时,Linux 先查找 /etc/passwd 文件中是否有这个用户名,没有 ...