P3225 [HNOI2012]矿场搭建

题目描述

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

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:

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

输出样例#1:

Case 1: 2 4
Case 2: 4 1

说明

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

Case 2 的一组解为(4,5,6,7)。

分情况讨论:

很显然是要求割点嘛、、、(分类上写着、、、)

好吧,求完割点以后干什么??

我一直认为是先求出割点,然后将割点全部炸掉(屏蔽)后求出每个联通块的点的个数,然后在用乘法原理来做。

结果发现全wa!!!(ORZ)

据说这道题要分类讨论、、、、

①若一个双联通中没有割点,那么最少需要两个出口(炸了一个去另一个)

②若一个双联通能连到一个割点,那么最少需要在双联通中设置一个出口,炸了割点还能逃生、

③若一个双联通能连到多余一个割点,那么不管怎么炸,都能从没炸的割点跑到别的分量里

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 510
using namespace std;
long long ans2;
bool vis[N],cut_point[N];
int n,m,x,y,s,tot,tim,cnt,cut,sum,ans1;
int dfn[N],low[N],head[N],belong[N];
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;
}
struct Edge
{int from,to,next;
}edge[N<<1];
int add(int x,int y)
{tot++;edge[tot].to=y;edge[tot].next=head[x];head[x]=tot;
}
int begin()
{memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(edge,0,sizeof(edge));memset(head,0,sizeof(head));memset(belong,0,sizeof(belong));memset(cut_point,0,sizeof(cut_point));n=0,tot=1,ans1=0,ans2=1,tim=0,sum=0;
}
int tarjan(int now,int pre)
{dfn[now]=low[now]=++tim;int tt=0; bool boo=false;for(int i=head[now];i;i=edge[i].next){int t=edge[i].to;if((1^i)==pre) continue;if(!dfn[t]){tt++;tarjan(t,i);low[now]=min(low[now],low[t]);if(dfn[now]<=low[t]) boo=true;}else low[now]=min(low[now],dfn[t]);}if(pre==-1) {if(tt>1) cut_point[now]=true;}else if(boo) cut_point[now]=true;
}
int dfs(int x)
{s++;vis[x]=true;belong[x]=sum;for(int i=head[x];i;i=edge[i].next){int t=edge[i].to;if(cut_point[t]&&belong[t]!=sum) cut++,belong[t]=sum;if(!vis[t]&&!cut_point[t]) dfs(t);}
}
int main()
{while(1){m=read();if(m==0) break;begin();for(int i=1;i<=m;i++){x=read(),y=read();add(x,y),add(y,x);n=max(max(x,y),n);}for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i,-1);for(int i=1;i<=n;i++){if(vis[i]||cut_point[i]) continue;s=0,cut=0;sum++;dfs(i);if(!cut) ans1+=2,ans2*=(long long)(s*(s-1)>>1);if(cut==1) ans1++,ans2*=(long long)s;}printf("Case %d: %d %lld\n",++cnt,ans1,ans2);}return 0;
}

傻不拉几的只考虑一种情况还调试半天、、、、结果全wa

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 11000
using namespace std;
bool vis[N],cut_point[N];
int n,m,tot,tim,sum,cnt,top,ans1,ans2;
int x[N],y[N],dfn[N],low[N],ans[N],head[N],stack[N],belong[N];
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;
}
struct Edge
{int from,to,next;
}edge[N];
int add(int x,int y)
{tot++;edge[tot].to=y;edge[tot].next=head[x];head[x]=tot;
}
int tarjan(int x,int pre)
{int s=0; bool boo;dfn[x]=low[x]=++tim;vis[x]=true;for(int i=head[x];i;i=edge[i].next){int t=edge[i].to;if((1^i)==pre) continue;if(!vis[t]){s++;tarjan(t,i);low[x]=min(low[t],low[x]);if(low[t]>=dfn[x]) boo=true;  }else low[x]=min(low[x],dfn[t]);}if(!pre) {if(s>1) cut_point[x]=true;}else {if(boo) cut_point[x]=true;}
}
int tarjan1(int now)
{dfn[now]=low[now]=++tim;stack[++top]=now;vis[now]=true;for(int i=head[now];i;i=edge[i].next){int t=edge[i].to;if(vis[t]) low[now]=min(low[now],dfn[t]);else if(!dfn[t]) tarjan1(t),low[now]=min(low[now],low[t]);}if(dfn[now]==low[now]){sum++; belong[now]=sum;ans[sum]++;for(;stack[top]!=now;top--)belong[stack[top]]=sum,vis[stack[top]]=false,ans[sum]++;vis[now]=false; top--;}
}
int begin()
{tot=0,tim=0,sum=0,ans2=1;memset(ans,0,sizeof(ans));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(vis,0,sizeof(vis));memset(head,0,sizeof(head));memset(belong,0,sizeof(belong));
}
int main()
{while(1){m=read();if(m==0) break;begin();cnt++,tot=1;memset(cut_point,0,sizeof(cut_point));for(int i=1;i<=m;i++)x[i]=read(),y[i]=read(),add(x[i],y[i]),add(y[i],x[i]);    tarjan(1,0); begin();for(int i=1;i<=m;i++){n=max(max(x[i],y[i]),n);if(cut_point[x[i]]||cut_point[y[i]]) continue;add(x[i],y[i]),add(y[i],x[i]); }for(int i=1;i<=n;i++)if(!dfn[i]&&!cut_point[i]) tarjan1(i);ans1=sum;for(int i=1;i<=sum;i++)ans2*=ans[i];printf("Case %d: %d %d\n",cnt,ans1,ans2);}return 0;
}

View Code

转载于:https://www.cnblogs.com/z360/p/7462485.html

洛谷——P3225 [HNOI2012]矿场搭建相关推荐

  1. 洛谷 P3225 [HNOI2012]矿场搭建

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

  2. LOJ洛谷P3225:矿场搭建(割点、点双)

    文章目录 解析 代码 解析 我的实现不够简洁,导致bug越调越谜- 关键就是**找被割点分开的分量的方法:dfs!!! 一下子就豁然开朗了 代码 #include<bits/stdc++.h&g ...

  3. P3225 [HNOI2012]矿场搭建 割点 tarjan 双联通分量

    https://www.luogu.org/problemnew/show/P3225  题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一 ...

  4. P3225 [HNOI2012]矿场搭建

    思路:$tarjan+组合$ 提交:1次 题解: 先$tarjan$求出割点,然后按连通块的性质分类讨论: 1.若没有与割点相连,则需要两个井,防止一个坏掉. 2.若有一个割点相连,修一个井,考虑井坏 ...

  5. P3225 [HNOI2012] 矿场搭建

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

  6. 点双连通分量 [HNOI2012]矿场搭建

    问题 F: [HNOI2012]矿场搭建 时间限制: 1 Sec  内存限制: 128 MB 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人 ...

  7. bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双

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

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

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2730 分析: 如果坍塌的点不是割点,那没什么影响,主要考虑坍塌的点是割点的情况. 显然 ...

  9. BZOJ 2733 | 洛谷 P3224 [HNOI2012]永无乡

    https://www.lydsy.com/JudgeOnline/problem.php?id=2733 https://www.luogu.org/problemnew/show/P3224 C+ ...

最新文章

  1. Docker镜像、容器数据卷和Dockerfile
  2. 从EXCHANGE03转移到EXCHANGE07
  3. 简单的文本片段替换器
  4. 【机器视觉学习笔记】最近邻插值实现图片任意角度旋转(C++)
  5. android开发 视图联动_android开发_ViewGroup(组视图)-- 五大布局
  6. UVa 1605 - Building for UN
  7. DBN-RBM TensorFlow实现
  8. Redis学习笔记三:多机数据库的实现
  9. 激光点云数据编辑处理(一)——CloudCompare
  10. 秋招总结--来自一枚2020届普通本科生的回顾
  11. STC12LE5612AD芯片使用心得(一)芯片介绍
  12. 2021年高压电工考试及高压电工考试题
  13. 安装英伟达显卡旧版驱动
  14. java实现一个旅游网站
  15. 手把手教你Photoshop中的图层混合模式(一)
  16. python批量发送邮件_python批量发邮件
  17. 给网站添加SSL安全证书
  18. Let's go to the EX
  19. 权限系统就该这么设计(万能通用),稳的一批!
  20. jq click()方法无反应?

热门文章

  1. AOP Aspect Oriented Programming
  2. STM32 IO口双向问题
  3. 源码编译搭建LAMP环境
  4. 【进阶修炼】——改善C#程序质量(9)
  5. javascript:void(0)的作用示例
  6. 前端智勇大闯关-第二季-第三题
  7. SnagIt的Visual Studio Team System插件
  8. 美国太空部队加入美国情报系统,以确保太空的安全
  9. 轻芒 CEO 王俊煜:高品质内容是核心,小程序是它的最好载体
  10. DiskGenius无损调整C盘容量方法