P3225 [HNOI2012]矿场搭建

题目描述

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

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

点双入门。。。 话说题意是真的晦涩。

一眼求割点,求完割点怎么办?

因为我们把割点去掉之后,图中会剩下一个一个的块,这些块就是点双。

那么限制工人逃跑的就是割点,所以我们在乎的是每个点双中有多少个割点。

那么我们就可以通过Tarjan给所有割点打上一个标记。

然后再去DFS出所有的点双,这个过程需要记录点双中的点和点双中的割点数。有些细节。

然后就可以愉快地分情况讨论了。

(一),当前点双内没有割点,那么这个点双是独立的也就是不和其他的块联通,那么对于这个点双内的点我们就需要建立两个救援出口,为什么呢,因为有一个炸了还有另外一个。所以\(ans1+=2\)

然后方案数通过乘法原理和组合数搞一搞就行了,也就是\(ans2*=C(tot,2)\)。

(二),当前点双内只有一个割点,那么可以知道如果这个割点炸了我们就翻车了,所以我们可以继承(一)的思想,只是把这个已有的割点看成一个必然的出口,所以我们还需要建1个出口,方案数为\(ans2*=C(tot,1)\)。

(三),当前点双内有两个割点,还是一样的思想,就会发现我们不用再建出口了,因为可以把两个割点看成两个出口,任意一个炸了我们还有另一个。

ok,那就可以开始愉快地写代码了喵喵喵。。。

code:

#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; #define int long long const int wx=517; inline int read(){
int sum=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
return sum*f;
} int n,m,ans1,ans2,num,sjc,tot,zmj,cnt;
int dfn[wx],head[wx],ok[wx],vis[wx],low[wx]; struct e{
int nxt,to;
}edge[wx*2]; void add(int from,int to){
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
} void Tarjan(int u,int f){
dfn[u]=low[u]=++tot; int child=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==f)continue;
if(!dfn[v]){
Tarjan(v,u);
child++;
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])ok[u]=1;
}
else if(dfn[v]<dfn[u]&&v!=f){
low[u]=min(low[u],dfn[v]);
}
}
if(child<=1&&f==-1)ok[u]=0;
} void dfs(int u){
vis[u]=tot; zmj++;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(vis[v]!=vis[u]&&ok[v])cnt++,vis[v]=tot;
if(!vis[v]&&!ok[v])dfs(v);
}
} void clear(){
num=0,tot=0;
memset(head,0,sizeof head);
memset(edge,0,sizeof edge);
memset(vis,0,sizeof vis);
memset(dfn,0,sizeof dfn);
memset(ok,0,sizeof ok);
} signed main(){
while(1){
m=read(); if(!m)break;
n=0; sjc++; ans1=0; ans2=1;
clear();
for(int i=1;i<=m;i++){
int x,y;
x=read(); y=read();
add(x,y); add(y,x); n=max(n,max(x,y));
}
for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,-1);
for(int i=1;i<=n;i++){
if(ok[i]||vis[i])continue;
tot++; zmj=0,cnt=0; dfs(i);
if(cnt==0)ans1+=2,ans2*=(zmj-1)*zmj/2;
if(cnt==1)ans1++,ans2*=zmj;
}
printf("Case %lld: %lld %lld\n",sjc,ans1,ans2);
}
return 0;
}

Tarjan 点双+割点+DFS【洛谷P3225】 [HNOI2012]矿场搭建的更多相关文章

  1. 洛谷 P3225 [HNOI2012]矿场搭建 解题报告

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

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

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

  3. 洛谷P3225 HNOI2012 矿场搭建

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

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

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

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

    传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...

  6. BZOJ2730或洛谷3225 [HNOI2012]矿场搭建

    BZOJ原题链接 洛谷原题链接 显然在一个点双连通分量里,无论是哪一个挖煤点倒塌,其余挖煤点就可以互相到达,而对于一个点双连通分量来说,与外界的联系全看割点,所以我们先用\(tarjan\)求出点双连 ...

  7. [Luogu] P3225 [HNOI2012]矿场搭建

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

  8. P3225 [HNOI2012]矿场搭建

    传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...

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

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

随机推荐

  1. 关于jquery在页面初始化时radio控件选定默认值的问题

    网上找了很多资料,都是比较旧版本的方法,新版的jquery都已经抛弃了. 正确的代码是 $('input:radio[name="statusRadios"][value=&quo ...

  2. C#操作SQLIte数据。

    using System; using System.Data; using System.Text.RegularExpressions; using System.Xml; using Syste ...

  3. Django的admin使用

    现在假设我们自己定义了一个用户模型和成员模型,我们需要在Django后台对它进行管理,使用admin可以对模型进行相关的展示设置和管理. from django.contrib import admi ...

  4. 设备控制接口ioctl详解

    [转]Linux设备控制接口 序言设备驱动程序的一个基本功能就是管理和控制设备,同时为用户应用程序提供管理和控制设备的接口.我们前面的“Hello World”驱动程序已经可以提供读写功能了,在这里我 ...

  5. 配置环境是程序员的第一步 -- Xshell 6 免费版下载安装

    Xshell 是一个强大的安全终端模拟软件,通常用来连接云主机,远程控制云主机. 很多人都不知道 Xshell 有专门为家庭和学校用户提供的免费版,只需要填个用户名和邮箱即可. 免费版链接:https ...

  6. java基础之io流总结二:File类基本应用

    File类的概述: File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹. File类保存文件或目录的各种元数据信息,包括文件名.文件长度.最后修改时间.是否可读 ...

  7. css字体属性(font)

    字体名称属性(font-family) 这个属性设定字体名称,如Arial, Tahoma, Courier等.例句如下: .s1 {font-family:Arial}     字体大小属性(fon ...

  8. solrcloud学习记录

    1.今天看了下solrcloud提供的软提交的作用 硬提交:solr的建索引数据是要在提交时写入磁盘的,这是确保即便是停电也不会丢失数据: 软提交:为了提供更实时的检索能力,Solr设定了一种软提交方 ...

  9. 【转】Provisional headers are shown

    在chrome开发者工具的 Network 面板中,某些请求头后面会跟着下面这行文字: Provisional headers are shown 这种请求实际上根本没有产生,对应的请求头当然也不应该 ...

  10. 2-chrome无法添加扩展程序

    1.更多工具->拓展程序->打开开发者模式->重启浏览器 2.将拓展程序拖入,确认安装