洛谷——P3225 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建
题目描述
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
输入输出格式
输入格式:
输入文件有若干组数据,每组数据的第一行是一个正整数 N(N<=500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖 S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。
输出格式:
输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。
输入输出样例
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
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() { ,f=; char ch=getchar(); ; ch=getchar();} +ch-'; 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 begin() { memset(vis,,sizeof(vis)); memset(dfn,,sizeof(dfn)); memset(low,,sizeof(low)); memset(edge,,sizeof(edge)); memset(head,,sizeof(head)); memset(belong,,sizeof(belong)); memset(cut_point,,sizeof(cut_point)); n=,tot=,ans1=,ans2=,tim=,sum=; } int tarjan(int now,int pre) { dfn[now]=low[now]=++tim; ; bool boo=false; for(int i=head[now];i;i=edge[i].next) { int t=edge[i].to; ^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]); } ) {) 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() { ) { m=read();) break; begin(); ;i<=m;i++) { x=read(),y=read(); add(x,y),add(y,x); n=max(max(x,y),n); } ;i<=n;i++) ); ;i<=n;i++) { if(vis[i]||cut_point[i]) continue; s=,cut=; sum++;dfs(i); ,ans2*=()>>); ) ans1++,ans2*=(long long)s; } printf("Case %d: %d %lld\n",++cnt,ans1,ans2); } ; }
傻不拉几的只考虑一种情况还调试半天、、、、结果全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() { ,f=; char ch=getchar(); ; ch=getchar();} +ch-'; 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) { ; 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; ^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]); } ) 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=,tim=,sum=,ans2=; memset(ans,,sizeof(ans)); memset(dfn,,sizeof(dfn)); memset(low,,sizeof(low)); memset(vis,,sizeof(vis)); memset(head,,sizeof(head)); memset(belong,,sizeof(belong)); } int main() { ) { m=read();) break; begin();cnt++,tot=; memset(cut_point,,sizeof(cut_point)); ;i<=m;i++) x[i]=read(),y[i]=read(),add(x[i],y[i]),add(y[i],x[i]); tarjan(,); begin(); ;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]); } ;i<=n;i++) if(!dfn[i]&&!cut_point[i]) tarjan1(i); ans1=sum; ;i<=sum;i++) ans2*=ans[i]; printf("Case %d: %d %d\n",cnt,ans1,ans2); } ; }
洛谷——P3225 [HNOI2012]矿场搭建的更多相关文章
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 洛谷P3225 HNOI2012 矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
- 洛谷 P3225 [HNOI2012]矿场搭建
传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...
- 洛谷—— P3225 [HNOI2012]矿场搭建
https://www.luogu.org/problem/show?pid=3225 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有 ...
- BZOJ2730或洛谷3225 [HNOI2012]矿场搭建
BZOJ原题链接 洛谷原题链接 显然在一个点双连通分量里,无论是哪一个挖煤点倒塌,其余挖煤点就可以互相到达,而对于一个点双连通分量来说,与外界的联系全看割点,所以我们先用\(tarjan\)求出点双连 ...
- P3225 [HNOI2012]矿场搭建 割点 tarjan 双联通分量
https://www.luogu.org/problemnew/show/P3225 题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条 ...
- P3225 [HNOI2012]矿场搭建 题解
这道题挺难的,可以加深对割点的理解,还有,排列组合好重要了,分连通块,然后乘法原理(加法原理计数什么的) 传送门 https://www.luogu.org/problem/P3225 省选oi题 ...
- P3225 [HNOI2012]矿场搭建
传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...
- [Luogu] P3225 [HNOI2012]矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
随机推荐
- DBMS的工作模式
数据库管理系统(DBMS)是指数据库系统中对数据进行管理的软件系统,它是数据库系统的核心组成部分,对数据库的一切操作(增删改查)都是通过DBMS进行的 DBMS的工作模式如下: 1>接受应用程序 ...
- 聊天室(C++客户端+Pyhton服务器)_1.框架搭设
聊天室 一.客户端发送 用MFC可视化做个客户端登录界面. 先点击注册账号按钮,注册账号的时候就需要连接到服务器, 服务器需要查数据库,并做出相应的回应. 所以开始写C++客户端套接口类用来连接到服务 ...
- mount nfs 各版本之间的转换
[root@one1-fst-hx ~]# mount.nfs 182.168.2.49:/mnt/sdb/nfs /mnt/nfs2/ nomand,-o vers=3[root@one1-fst- ...
- unix网络编程-配置unp.h头文件
第一步进入:www.unpbook.com,下载unp的随书代码.新建一个目录,将压缩包拷贝到这一目录下面,然后将压缩包直接解压:tar -zxvf 压缩包名.tar.gz 完成上一步后,进入到un ...
- 自己写的画loss曲线代码
import matplotlib.pyplot as plt iteration = [] loss = [] with open('/home/sensetime/log.txt','r') as ...
- python爬虫---从零开始(一)初识爬虫
我们开始来谈谈python的爬虫. 1,什么是爬虫: 网络爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫.互联网犹如一个大蜘蛛 ...
- python基础:函数传参、全局变量、局部变量、内置函数、匿名函数、递归、os模块、time模块
---恢复内容开始--- 一.函数相关: 1.1位置参数: ef hello(name,sex,county='china'): pass #hello('hh','nv') #位置参数.默认参数 1 ...
- 关于DTCC数据库技术大会
本次DTCC数据库技术大会是第9届了,这次大会虽然有不少公司的产品推介,总体来说还是有不少干货的. 专场较多,有选择地主要听了大数据实践跟流式计算这块.网易跟滴滴的分享比较不错. 了解到了现在大家是用 ...
- CentOS7.4搭建kafka单结点和集群
操作系统选择 CentOS7.4x86-64(操作系统的x86_64是跟CPU有关的,最早AMD公司开发出了一款向下兼容x86CPU,向上又扩充了指令集,具有了64位CPU的特性,这款CPU后来改名为 ...
- perl学习之:@_ $_
question 1 :数组@xxx调用时,每个元素应该用$xxx[0]/$xxx[1]... 来表示所以$_[0]表示@_的一个元素,和默认缺省变量$_无关,是两个东西请查阅数组元素调用相关章节 ...