博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ-2730】矿场搭建 Tarjan 双连通分量
阅读量:4582 次
发布时间:2019-06-09

本文共 2523 字,大约阅读时间需要 8 分钟。

2730: [HNOI2012]矿场搭建

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1602  Solved: 751
[][][]

Description

煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

Input

输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖       S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。

Output

输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。

Sample Input

9
1 3
4 1
3 5
1 2
2 6
1 5
6 3
1 6
3 2
6
1 2
1 3
2 4
2 5
3 6
3 7
0

Sample Output

Case 1: 2 4
Case 2: 4 1

HINT

Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);
Case 2 的一组解为(4,5,6,7)。

Source

Solution

对于删除一个点,其余点要有出路,显然是和割点有关,那么我们求出所有割点,以及双连通分量。

对于一个双联通分量中,如果我们只删除一个割点或非割点,那么如果还有其余割点能使其余点到关键点,那么显然是不需要额外考虑的;如果没有其余的割点令我们到关键点,那么我们需要新建额外的关键点

分情况讨论,如果一个双联通分量里,有两个及以上割点,那么这个双联通分量里面是不需要额外建的

如果一个双联通分量里只有一个或没有割点,那么我们只需要再建一个即可。

至于方案数,可以利用乘法原理,我们把每个连通分量里的每个可以用来建成关键点的点用乘法统计起来即可

Code

#include
#include
#include
#include
#include
#include
using namespace std;#define LL long longinline int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f;}#define MAXM 1010 #define MAXN 80010int N,M,tot;LL sum;struct EdgeNode{ int next,to,from;}edge[MAXM<<1];int head[MAXN],cnt=1;void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}#define Pa pair
vector
BCC[MAXN];Pa st[MAXM]; int top;int dfn[MAXN],low[MAXN],dfsn,cut[MAXN],bcc,belong[MAXN];void Tarjan(int now,int last){ dfn[now]=low[now]=++dfsn; int son=0; for (int i=head[now]; i; i=edge[i].next) if (!dfn[edge[i].to]) { st[++top]=make_pair(now,edge[i].to); son++; Tarjan(edge[i].to,now); low[now]=min(low[now],low[edge[i].to]); if (dfn[now]<=low[edge[i].to]) { cut[now]=1; bcc++; BCC[bcc].clear(); int tnow=-1,tto=-1; while (1) { tnow=st[top].first,tto=st[top].second; top--; if (belong[tnow]!=bcc) BCC[bcc].push_back(tnow),belong[tnow]=bcc; if (belong[tto]!=bcc) BCC[bcc].push_back(tto),belong[tto]=bcc; if (tnow==now && tto==edge[i].to) break; } } } else if (dfn[edge[i].to]

 

转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5903855.html

你可能感兴趣的文章
realsense blog 国外某人
查看>>
点击按钮将内容赋值到粘贴板
查看>>
DevExpress12.2.6 安装顺序记录
查看>>
.Net基础篇_学习笔记_第四天_switch-case02
查看>>
linux之基本命令讲解
查看>>
DAG上dp思想
查看>>
写文件
查看>>
HDU5367 思维map // 动态线段树
查看>>
洛谷P1501 动态树(LCT)
查看>>
usaco Shuttle Puzzle
查看>>
SQLServer数据库的状态一直都是正在还原
查看>>
EM算法总结
查看>>
剑指Offer——二叉树的下一个节点
查看>>
关于virtualenvwrapper的python, pip 的版本的问题
查看>>
iOS获取APP的版本号和名称
查看>>
如何用keytool导入证书
查看>>
[转]linux14.04下caffe的安装步骤
查看>>
重操JS旧业第十弹:闭包
查看>>
JSP 自动刷新
查看>>
ORACLE 如何产生一个随机数
查看>>