P3225 [HNOI2012]矿场搭建[割点]
题目描述
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
解析
这道题不错,很考验思考问题的全面性,而且代码写起来似乎也比较坑。
咱写挂了(哭)。
乍一看似乎第一问就是要我们求连通块个数,第二问就是要我们求每个连通块中点的个数。
对,但这只是一小部分,我们少考虑了一些东西。
这道题需要分类讨论。
- 如果某个连通块一个割点都没有会怎么样?那么在这个子图中,我们在任意两个位置设置出口即可,对于该连通块,若其包含\(x\)个点,其方案数为\(x(x-1)/2\)。
- 如果某个连通块只有一个割点,我们在此连通块的任意一点都可以放置出口,并统计方案数。
- 特别特别需要注意的一个坑点,我们在考虑设置出口时,要知道此题只会出现一个坍塌的挖煤点!所以,如果某个连通块有两个及以上个割点,其还是可以与其它连通块相连,所以这个连通块中是不必设置出口的!
这题最核心的一点就是要注意到只会出现一个坍塌点,所以任何时候我们都只用考虑只有一个割点时的情况。
提一些细节,在dfs划分连通块时,我们不能只记某个点是否到达过,我们得记它属于哪个连通块,否则会少算一些或者是算重复一些(这个还要看你怎么写)。
为什么要提呢,因为我写错了,我甚至还没有注意到只会出现一个坍塌点。
参考代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define N 501
using namespace std;
inline ll read()
{
ll f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct rec{
int next,ver;
}g[N*N];
ll head[N],tot,n,m,low[N],dfn[N],cnt,root,c[N],num,k,now;
ll ans1,ans2;
bool cut[N];
ll v[N];
inline void add(int x,int y)
{
g[++tot].ver=y;
g[tot].next=head[x],head[x]=tot;
}
inline void tarjan(int x)//tarjan求割点板子
{
low[x]=dfn[x]=++cnt;
int flag=0;
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
flag++;
if(x!=root||flag>1) cut[x]=1;
}
}
else low[x]=min(low[x],dfn[y]);
}
}
inline void dfs(int x)
{
v[x]=num;++k;//划分连通块num,统计该连通块中点的个数k
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver;
if(v[y]!=num&&cut[y]) v[y]=num,now++;//这里卡了我许久,这样写才能避免重复计算该连通块包含割点数量
if(!v[y]) dfs(y);
}
}
int main()
{
int kase=0;
while(~scanf("%d",&n)&&n){
memset(head,0,sizeof(head));
memset(cut,0,sizeof(cut));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(v,0,sizeof(v));
tot=ans2=1;ans1=m=0;
for(int i=1;i<=n;++i){
ll u,v;
u=read(),v=read();
add(u,v),add(v,u);
m=max(m,max(v,u));
}
cnt=num=0;
for(int i=1;i<=m;++i)
if(!dfn[i]) root=i,tarjan(i);
for(int i=1;i<=m;++i)
if(!v[i]&&!cut[i]){
k=now=0,num++;
dfs(i);
if(now==0){//注意,这里是重点
ans1+=2;
ans2*=(k-1)*k/2;
}
if(now==1) ans1++,ans2*=k;
}
printf("Case %d: %lld %lld\n",++kase,ans1,ans2);
}
return 0;
}
P3225 [HNOI2012]矿场搭建[割点]的更多相关文章
- P3225 [HNOI2012]矿场搭建 割点 tarjan 双联通分量
https://www.luogu.org/problemnew/show/P3225 题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条 ...
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 洛谷——P3225 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- P3225 [HNOI2012]矿场搭建 tarjan割点
这个题需要发现一点规律,就是先按割点求块,然后求每个联通块中有几个割点,假如没有割点,则需要建两个出口,如果一个割点,则需要建一个出口,2个以上不用建. 题干: 题目描述 煤矿工地可以看成是由隧道连接 ...
- P3225 [HNOI2012]矿场搭建 题解
这道题挺难的,可以加深对割点的理解,还有,排列组合好重要了,分连通块,然后乘法原理(加法原理计数什么的) 传送门 https://www.luogu.org/problem/P3225 省选oi题 ...
- 洛谷P3225 HNOI2012 矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
- 洛谷 P3225 [HNOI2012]矿场搭建
传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...
- P3225 [HNOI2012]矿场搭建
传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...
- [Luogu] P3225 [HNOI2012]矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
随机推荐
- python jieba
https://www.cnblogs.com/jiayongji/p/7119065.html 安装 pip install jieba 简单用法 结巴分词分为三种模式:精确模式(默认).全模式和搜 ...
- linux echo -e 处理特殊字符
linux echo -e 处理特殊字符 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:\a 发出警告声:\b 删除前一个字符:\c 最后不加上换行符号:\f 换行但光标仍旧停留 ...
- 学习数据结构Day2
之前学习过了数组的静态实现方法,同时将数组的所有有可能实现的方法都统一实现了一遍,之后支持了泛型的相关 概念,接下来就是如何对数组进行扩容的操作也就是实现动态数组. private void resi ...
- 11 Sping框架--AOP的相关概念及其应用
1.AOP的概念 AOP(Aspect Oriented Programming 面向切面编程),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一 ...
- [转帖]都在说DCEP,央行数字货币究竟跟你有什么关系?
都在说DCEP,央行数字货币究竟跟你有什么关系? https://kuaibao.qq.com/s/20191104A0G1D300?refer=spider 黄奇帆指出,DCEP 使得交易环节对 ...
- liunx mysql数据库目录迁移
1.查看mysql安装目录 从目录etc/my.cnf中查看安装目录 2.进入mysql目录,停止mysql服务 命令: cd usr/local/mysql 命令:service mysql sto ...
- Java生成菜单树(目录树)的几种方式
本文介绍两种不同生成多级目录树的方式:1. 递归生成,2. map+list 集合生成.最下方会附上完整代码. 生成树的基本规则:子节点的par_id等于父节点的id. 1. 实体类 import ...
- 关于类视图选择继承APIView还是工具视图(ListAPIView、CreateAPIView等等)
APIView使用方法,直接继承APIView,get或者post请求.方法很简单1.先获取到要操作的数据,然后把数据放到serializer中序列化或者反序列化,最后return返回值(记得.dat ...
- gorm 实现 mysql for update 排他锁
关于 MySQL 的排他锁网上已经有很多资料进行了介绍,这里主要是记录一下 gorm 如果使用排他锁. 排他锁是需要对索引进行锁操作,同时需要在事务中才能生效.具体操作如下: 假设有如下数据库表结构: ...
- Luogu4233 射命丸文的笔记 DP、多项式求逆
传送门 注意到总共有\(\frac{n!}{n}\)条本质不同的哈密顿回路,每一条哈密顿回路恰好会出现在\(2^{\binom{n}{2} - n}\)个图中,所以我们实际上要算的是强连通有向竞赛图的 ...