bzoj2730: [HNOI2012]矿场搭建

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)。

题解:

这题简直就是暴力。。。

显然在某个不是割点的点坍塌并没有什么事,考虑在割点坍塌的情况

先把所以的割点求出来然后删掉,现在会剩下若干个连通块

如果只有一个连通块,显然这个图没有割点,答案为n*(n-1)/2

如果一个连通块可以连接不少于两个,它就不用设置救援出口,否则要设置一个

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 505
 7 using namespace std;
 8 char ch;
 9 bool ok;
10 void read(int &x){
11     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
12     for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
13     if (ok) x=-x;
14 }
15 int n,m,a[maxn],b[maxn],u,v;
16 int list[maxn<<1];
17 int tot,now[maxn],son[maxn<<1],pre[maxn<<1];
18 int idx,dfn[maxn],low[maxn],deg,cnt,color[maxn],siz[maxn],sum[maxn],total,vis[maxn];
19 long long ans;
20 bool flag,bo[maxn];
21 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
22 void dfs(int u,int fa){
23     dfn[u]=low[u]=++idx;
24     for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
25         if (!dfn[v]){
26             dfs(v,u);
27             low[u]=min(low[u],low[v]);
28             if (dfn[u]<=low[v]){if (u!=1) flag=1,bo[u]=1; else deg++;}
29         }
30         else if (v!=fa) low[u]=min(low[u],dfn[v]);
31 }
32 void dfs2(int u){
33     vis[u]=cnt,siz[cnt]++;
34     for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
35         if (!bo[v]){if (vis[v]!=cnt) dfs2(v);}
36         else if (vis[v]!=cnt) vis[v]=cnt,sum[cnt]++;
37 }
38 int main(){
39     int tim=0;
40     for (read(m);m;read(m)){
41         n=tot=0,tim++;
42         memset(now,0,sizeof(now));
43         for (int i=1;i<=m;i++) read(a[i]),read(b[i]),list[++n]=a[i],list[++n]=b[i];
44         sort(list+1,list+n+1),n=unique(list+1,list+n+1)-list-1;
45         for (int i=1;i<=m;i++){
46             u=lower_bound(list+1,list+n+1,a[i])-list;
47             v=lower_bound(list+1,list+n+1,b[i])-list;
48             put(u,v),put(v,u);
49         }
50         memset(dfn,0,sizeof(dfn));
51         memset(low,0,sizeof(low));
52         idx=deg=0,flag=0;
53         memset(bo,0,sizeof(bo));
54         dfs(1,0);
55         if (deg>1) flag=1,bo[1]=1;
56         if (!flag) printf("Case %d: %d %d\n",tim,2,n*(n-1)/2);
57         else{
58             memset(vis,0,sizeof(vis));
59             memset(siz,0,sizeof(siz));
60             memset(sum,0,sizeof(sum));
61             total=cnt=0,ans=1;
62             for (int i=1;i<=n;i++) if (!bo[i]&&!vis[i]){
63                 ++cnt,dfs2(i);
64                 if (sum[cnt]==1) ans=ans*siz[cnt],total++;
65             }
66             printf("Case %d: %d %lld\n",tim,total,ans);
67         }
68     }
69     return 0;
70 }
时间: 2024-08-04 04:18:45

bzoj2730: [HNOI2012]矿场搭建的相关文章

[BZOJ2730][HNOI2012]矿场搭建(求割点)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2730 分析: 如果坍塌的点不是割点,那没什么影响,主要考虑坍塌的点是割点的情况. 显然我们可以先求出所有割点把整个图分成若干个连通块 如果一个联通块只与一个割点相连,说明我们必须在这个连通块中选一个点作为出口 如果一个联通块与两个以上的割点相连,那么就可以不在这些点取一个作为出口 方案数就是要取点的联通块的点的个数的乘积 注意没有割点的情况要放2个点

【双连通分量】Bzoj2730 HNOI2012 矿场搭建

Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Sulotion 坍塌的不是割顶并不影响,建在割顶也没有意义(拆割顶) 考虑每一个双连通分量,如果只连一个割顶必须内部建一个(随便选一个),连两个以上可以

BZOJ 2730:[HNOI2012]矿场搭建(割点+连通块)

[HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数.Input 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空

[HNOI2012]矿场搭建 题解

[HNOI2012]矿场搭建 时间限制: 1 Sec  内存限制: 128 MB 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. 输入 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的

洛谷——P3225 [HNOI2012]矿场搭建

P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口. 请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. 输入输出格式 输入格式: 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N<=500),表示工地的隧道数,接下来的

【BZOJ-2730】矿场搭建 Tarjan 双连通分量

2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Status][Discuss] Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用

cogs——1348. [HNOI2012]矿场搭建

1348. [HNOI2012]矿场搭建 ★★★   输入文件:bzoj_2730.in   输出文件:bzoj_2730.out   简单对比时间限制:1 s   内存限制:128 MB [题目描述] 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少

【bzoj2730】 HNOI2012—矿场搭建

http://www.lydsy.com/JudgeOnline/problem.php?id=2730 (题目链接) 题意 给出一张图,问如果删掉其中一个点,使得其他每个节点都有一个安全撤离的出口,最少需要设立多少个出口,有多少种方案. Solution 很明显,一张图至少要设立2个出口(一个点双连通分量),如果删掉不是割点的点,对答案不会有什么限制,考虑删掉的点是割点. 我们对割点以外的联通快进行染色,每一种颜色就表示在这些同样的颜色中的节点至少要设置一个出口,若一个节点被染成了多种颜色,那

[HNOI2012]矿场搭建

明明是Acm World Finals 2011的原题,把数据范围改小了就放出来了?!这样不好,, 昨天讲完双连通分量今天A一道点双的题. Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Input 输