bzoj2730: [HNOI2012]矿场搭建
2016-01-03 11:08
323 查看
Description
[align=left]煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。[/align]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
91 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 4Case 2: 4 1
HINT
[align=left]Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);[/align][align=left]Case 2 的一组解为(4,5,6,7)。[/align]
题解:
这题简直就是暴力。。。
显然在某个不是割点的点坍塌并没有什么事,考虑在割点坍塌的情况
先把所以的割点求出来然后删掉,现在会剩下若干个连通块
如果只有一个连通块,显然这个图没有割点,答案为n*(n-1)/2
如果一个连通块可以连接不少于两个,它就不用设置救援出口,否则要设置一个
code:
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #define maxn 505 using namespace std; char ch; bool ok; void read(int &x){ for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); if (ok) x=-x; } int n,m,a[maxn],b[maxn],u,v; int list[maxn<<1]; int tot,now[maxn],son[maxn<<1],pre[maxn<<1]; int idx,dfn[maxn],low[maxn],deg,cnt,color[maxn],siz[maxn],sum[maxn],total,vis[maxn]; long long ans; bool flag,bo[maxn]; void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;} void dfs(int u,int fa){ dfn[u]=low[u]=++idx; for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!dfn[v]){ dfs(v,u); low[u]=min(low[u],low[v]); if (dfn[u]<=low[v]){if (u!=1) flag=1,bo[u]=1; else deg++;} } else if (v!=fa) low[u]=min(low[u],dfn[v]); } void dfs2(int u){ vis[u]=cnt,siz[cnt]++; for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){if (vis[v]!=cnt) dfs2(v);} else if (vis[v]!=cnt) vis[v]=cnt,sum[cnt]++; } int main(){ int tim=0; for (read(m);m;read(m)){ n=tot=0,tim++; memset(now,0,sizeof(now)); for (int i=1;i<=m;i++) read(a[i]),read(b[i]),list[++n]=a[i],list[++n]=b[i]; sort(list+1,list+n+1),n=unique(list+1,list+n+1)-list-1; for (int i=1;i<=m;i++){ u=lower_bound(list+1,list+n+1,a[i])-list; v=lower_bound(list+1,list+n+1,b[i])-list; put(u,v),put(v,u); } memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); idx=deg=0,flag=0; memset(bo,0,sizeof(bo)); dfs(1,0); if (deg>1) flag=1,bo[1]=1; if (!flag) printf("Case %d: %d %d\n",tim,2,n*(n-1)/2); else{ memset(vis,0,sizeof(vis)); memset(siz,0,sizeof(siz)); memset(sum,0,sizeof(sum)); total=cnt=0,ans=1; for (int i=1;i<=n;i++) if (!bo[i]&&!vis[i]){ ++cnt,dfs2(i); if (sum[cnt]==1) ans=ans*siz[cnt],total++; } printf("Case %d: %d %lld\n",tim,total,ans); } } return 0; }
相关文章推荐
- 基于javascript实现简单计算器功能
- Unity中使用ulua的个人经验总结
- 计算机网络学习(三)——网络层
- 逻辑斯蒂回归模型
- c++ --单例的实现
- Delphi下 多显示器,将窗体显示于第二个显示器
- HDU 5607 graph
- 图片下载并保存到SD卡
- Java中Runnable和Thread的区别
- web开发中的路径问题
- Python 爬虫的实践运用(1)--爬取百度百科的词条
- Gradle for Android 第三篇( 依赖管理 )
- win10自带邮箱无法和163网易邮箱同步该怎么办?
- objectarx开发的环境设置
- 数据结构之一般树的基本操作
- css float 布局
- 详解Javascript事件驱动编程
- Find The Multiple
- AFN网络框架2.x版—网络监控
- Find The Multiple