[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个以上不用建. 题干: 题目描述 煤矿工地可以看成是由隧道连接 ...
随机推荐
- socket listen backlog
http://stackoverflow.com/questions/4253454/question-about-listening-and-backlog-for-sockets The list ...
- [Codeforces 140C] New Year Snowmen
[题目链接] https://codeforces.com/problemset/problem/140/C [算法] 显然 , 我们每次应优先考虑数量多的雪球 将雪球个数加入堆中 , 每次取出数量前 ...
- 21 WPF数据视图
视图对象 当你绑定集合到ItemsControl,在幕后数据视图被安静地创造.视图位于数据源和绑定控件之间.数据视图是通往数据源的一个窗口.它跟踪当前项目,它支持诸如排序,过滤,和分组特征.这些特征独 ...
- bzoj4269
http://www.lydsy.com/JudgeOnline/problem.php?id=4269 裸线性基,一个数取多次就是没取... 又有了些新的理解:a数组的前now个元素是基底,也就是可 ...
- is not mapped [from错误
我出现的错误是:org.hibernate.hql.ast.QuerySyntaxException: loginuser is not mapped [from loginuser] 配置文件如下: ...
- java笔记线程方式2
方式2:实现Runnable接口 * 步骤: * A:自定义类MyRunnable实现Runnable接口 * B:重写run()方法 * C:创建MyRunnable类的对象 * D ...
- poj 2409 Let it Bead【polya定理+burnside引理】
两种置换 旋转:有n种,分别是旋转1个2个--n个,旋转i的循环节数位gcd(i,n) 翻转:分奇偶,对于奇数个,只有一个珠子对一条边的中点,循环节数为n/2+1:对于偶数个,有珠子对珠子和边对边,循 ...
- RandomAccessFile使用场景及总结
大家在学到Java中IO流的时候学到了各种流,对文件的各种操作.但是唯独可能对RandomAccessFile对象不会去过多的研究,那么这个到底有什么用呢? RandomAccessFile的唯一父类 ...
- c++ rand && srand 函数
RAND: 结构:rand() 注:rand()不需要参数,它会根据种子返回一个从0到最大随机数的任意整数. 作用:生成一个随机数. 头文件:#include <cstdlib> ...
- HDU 1007 平面上最近点对 分治
思路: 分治 套路题 //By SiriusRen #include <cmath> #include <cstdio> #include <algorithm> ...