https://www.lydsy.com/JudgeOnline/problem.php?id=2730

https://www.luogu.org/problemnew/show/P3225

听说这是一道水题我就来做了,然而并不水……

煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。

请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

把点双缩起来,然后对于每个点双:

1.没有割点

说明点双内的点无法出去到其他点双,在这个点双内就需要两个出口,防止其中一个被炸。

(这是真的坑,忘了还可以炸出口orz)

2.有一个割点

只有一条路通往外面的点双,所以在点双内建一个出口。

3.有多个割点

有多条路通往外面的点双,炸了一条仍然与外面联通,所以不需要出口。

之后乘法原理做即可。

#include<cstdio>
#include<cmath>
#include<vector>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long ll;
const int N=1e3+;
inline int read(){
int x=,w=;char ch=;
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*w;
}
struct node{
int u,v,nxt;
}e[N];
int head[N],cnt,n,m,rtson;
int dfn[N],low[N],to[N],t,l;
bool cut[N];
stack<int>q;
vector<int>p[N];
inline int add(int u,int v){
e[++cnt].v=v;e[cnt].u=u;e[cnt].nxt=head[u];head[u]=cnt;
}
void tarjan(int u,int f){
dfn[u]=low[u]=++t;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
q.push(i);
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
int num;cut[u]=;
p[++l].clear();
do{
num=q.top();q.pop();
int uu=e[num].u,vv=e[num].v;
if(to[uu]!=l){
to[uu]=l;
p[l].push_back(uu);
}
if(to[vv]!=l){
to[vv]=l;
p[l].push_back(vv);
}
}while(num!=i);
}
if(!f)rtson++;
}else if(low[u]>dfn[v]&&f!=v){
q.push(i);
low[u]=dfn[v];
}
}
if(!f&&rtson<)cut[u]=;
}
inline void init(){
cnt=t=l=rtson=n=;
memset(head,,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(cut,,sizeof(cut));
memset(to,,sizeof(to));
}
int main(){
int test=;
while(scanf("%d",&m)&&m){
init();test++;
for(int i=;i<=m;i++){
int u=read(),v=read();
add(u,v);add(v,u);
n=max(n,u);n=max(n,v);
}
for(int i=;i<=n;i++)
if(!dfn[i])tarjan(i,);
ll num=,ans=;
for(int i=;i<=l;i++){
int sum=;
for(int j=;j<p[i].size();j++){
int u=p[i][j];
if(cut[u])sum++;
if(sum>)break;
}
ll sz=p[i].size();
if(!sum){
int tmp=min(2LL,sz);
num+=tmp;
if(tmp==)ans*=(ll)sz*(sz-)/;
}else if(sum==){
num++;
ans*=(sz-);
}
}
printf("Case %d: %lld %lld\n",test,num,ans);
}
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

最新文章

  1. 全球PM25实时可视化
  2. Vue - class与style绑定
  3. 谈谈yii2-GridView如何实现列表页直接修改数据
  4. javascript检查移动设备是否支持重力方向感应
  5. Android中分页滑动实现总结
  6. SQL Server 2016将内置R语言?
  7. [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  8. OpenShare新功能@2014年11月 [2014-11-30]
  9. CentOS下防火墙的基本操作命令
  10. NSMutableAttributedString iOS 在UILabel显示不同的字体和颜色(转)
  11. B/S的验证控件
  12. Jsp学习(2)
  13. Linux系统编程(2)——文件与IO之系统调用与文件IO操作
  14. Stitch Fix 融资1200万美元,又一个时尚创业的哈佛女MBA |华丽志
  15. HttpListener 实现web服务端
  16. Devstack: A copy of worked local.conf I&#39;m sharing with you.
  17. WIP 投料报 Invalid Serial Number
  18. crawlspider
  19. MSSQL 漏洞利用与提权
  20. PAT B1013

热门文章

  1. git 取消commit
  2. wireshark抓包分析——TCP/IP协议
  3. Qt-LCD电子时钟
  4. linux命令(实用!)
  5. 375. Clone Binary Tree【LintCode java】
  6. loadrunner_遇到cookie接口_3种应对方法
  7. Java学习 &#183; 初识 容器和数据结构
  8. (原) MaterialEditor部- UmateriaEditor中 Node编译过程和使用(1)
  9. git revert 与 git reset
  10. Java进阶知识点:服务端高并发的基石 - NIO与Reactor AIO与Proactor