点此看题面

大致题意: 一张无向图,要求你在去掉任意一个节点之后,剩余的每个节点都能到达一个救援出口,问至少需要几个救援出口。

第一步:\(Tarjan\)求割点

首先,我们要跑一遍\(Tarjan\)来求出割点

求完割点后,这样我们就能求出原图除了割点以外其他点所形成的若干个联通块(相当于把割点去掉之后形成的联通块)。

第二步:分类讨论

接下来,我们要对上面求出来的每一个联通块相邻的割点个数进行分类讨论:

  • 如果当前联通块相邻的割点个数为0

    显然对于这个联通块我们需要造2个救援出口,不然万一一个救援出口崩塌了,就出不去了。

    而方案数就相当于\(C_{Size}^2\),即\(\frac{Size(Size-1)}2\)。

  • 如果当前联通块相邻的割点个数为1

    那么对于这个联通块我们只需要造一个救援出口,因为就算救援出口崩塌了,还可以通过割点去另一个联通块内的救援出口。

    而方案数就是\(Size\)。

  • 如果当前联通块相邻的割点个数大于等于2

    那么对于这个联通块我们就不需要造救援出口了,因为就算某个割点崩塌了,我们依然可以通过另一个割点到达其它联通块的救援出口。

这样代码实现就不难了。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?-(x):(x))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=ch:(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=ch))
#define N 500
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,m,ans1=0,ee=0,cnt=0,d=0,top=0,Exist[N+5],lnk[N+5],dfn[N+5],low[N+5],vis[N+5],IsCut[N+5],used[N+5],Size[N+5],tot[N+5],Stack[N+5];
ull ans2=1;
struct edge
{
int to,nxt;
}e[2*N+5];
inline void read(int &x)
{
x=0;static char ch;
while(!isdigit(ch=tc()));
while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline void write(ull x)
{
if(x>9) write(x/10);
pc(x%10+'0');
}
inline void Tarjan(int x,int lst)//用Tarjan找割点
{
register int i,tot=0;
for(dfn[x]=low[x]=++d,i=lnk[x];i;i=e[i].nxt)
{
if(!(e[i].to^lst)) continue;
if(!dfn[e[i].to])
{
Tarjan(e[i].to,x),low[x]=min(low[x],low[e[i].to]),++tot;
if(lst&&low[e[i].to]>=dfn[x]) IsCut[x]=1;
}
else low[x]=min(low[x],dfn[e[i].to]);
}
if(!lst&&tot>=2) IsCut[x]=1;
}
inline void dfs(int x)//dfs遍历除去割点后的一个联通块
{
register int i,v;
for(Size[x]=vis[x]=1,tot[x]=0,i=lnk[x];i;i=e[i].nxt)//枚举每一个相邻的节点
{
if(IsCut[v=e[i].to])//如果这个节点是割点
{
if(!used[v]) used[Stack[++top]=v]=1,++tot[x];//如果这个割点没有访问过,就标记这个割点已访问,并将这个联通块相邻的割点个数加1
continue;//跳过
}
if(!vis[v]) dfs(v),Size[x]+=Size[v],tot[x]+=tot[v];//如果这个节点没被访问过,就去访问这个节点,并更新当前节点信息
}
}
int main()
{
register int i,j,x,y,T=0;
while(read(n),n)
{
for(ans1=ee=0,ans2=i=1;i<=n+1;++i) lnk[i]=dfn[i]=low[i]=IsCut[i]=Exist[i]=vis[i]=0;//初始化,将数组清空
for(i=1;i<=n;++i) read(x),read(y),add(x,y),add(y,x),Exist[x]=Exist[y]=1;
for(i=1;i<=n+1;++i) if(Exist[i]&&!dfn[i]) Tarjan(i,0);//Tarjan求割点
for(i=1;i<=n+1;++i)
{
if(!Exist[i]||IsCut[i]||vis[i]) continue;//如果这个节点不存在,或这个节点是割点,或这个节点已经被访问过,就跳过
top=0,dfs(i);//dfs遍历这个联通块
while(top) used[Stack[top--]]=0;//将访问过的割点标记为未访问
if(!tot[i]) ans1+=2,ans2*=1LL*Size[i]*(Size[i]-1)>>1;//如果这个联通块相邻的割点数为0,就需要加两个救援出口,方案数为Size(Size-1)/2
else if(tot[i]==1) ++ans1,ans2*=Size[i]; //如果这个联通块相邻的割点数为1,就需要加一个救援出口,方案数为Size
//如果这个联通块相邻的割点数大于等于2,就不需要加救援出口了
}
pc('C'),pc('a'),pc('s'),pc('e'),pc(' '),write(++T),pc(':'),pc(' '),write(ans1),pc(' '),write(ans2),pc('\n');//输出答案
}
return fwrite(pp,1,pp_,stdout),0;
}

【BZOJ2730】[HNOI2012] 矿场搭建(找割点)的更多相关文章

  1. BZOJ2730 [HNOI2012]矿场搭建 - Tarjan割点

    Solution 输入中没有出现过的矿场点是不用考虑的, 所以不用考虑只有 一个点 的点双联通分量. 要使某个挖矿点倒塌, 相当于割去这个点, 所以我们求一遍割点和点双联通分量. 之后的点双联通分量构 ...

  2. [BZOJ2730][HNOI2012]矿场搭建 点双 割点

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2852  Solved: 1344[Submit][Stat ...

  3. bzoj2730 [HNOI2012]矿场搭建 (UVAlive5135 Mining Your Own Business)

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1147  Solved: 528[Submit][Statu ...

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

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

  5. [HNOI2012]矿场搭建(割点)

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

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

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

  7. BZOJ2730:[HNOI2012]矿场搭建(双连通分量)

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

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

    看到删去一个点,需要剩下的都和关键点连通,有端联想到找点双,因为他怎么删点都是连通的. 对于一个孤立的点双,至少要设两个关键点. 如果两个点双以一个割点连接,假设断掉这个割点,两个块至少要各设一个关键 ...

  9. BZOJ2730: [HNOI2012]矿场搭建

    传送门 图的连通性相关的必和割点割边之类的有关. 题目要求对于一个无向图,任意一点被删除后,所有点都和某些指定点是联通的. 这道题比较简单的做法就是求出来所有的块.对于一个块,如果块里有两个及两个以上 ...

  10. BZOJ2730——[HNOI2012]矿场搭建

    bzoj2730 & world final 2011 H 1.题目大意:就是有一个无向图,让你在里面选择点,使得,无论哪个点没了以后,其他的点都能到达你选择的任何一个点,输出最少 选择几个点 ...

随机推荐

  1. ZOJ 2849【瞎暴力的搜索】

    思路: 靠评测机抖一抖的思路: 拿个队列维护一下符合类型的可以搜索(指四周还存在可以遍历的点)的点.然后暴力搜索,所以问题来了,这个暴力搜索会大大地重复遍历次数. DFS遍历图以前一直忽略重复,以为搜 ...

  2. Java8 使用 stream().filter()过滤List对象(查找符合条件的对象集合)

    内容简介 本文主要说明在Java8及以上版本中,使用stream().filter()来过滤一个List对象,查找符合条件的对象集合. List对象类(StudentInfo) public clas ...

  3. [Xcode 实际操作]三、视图控制器-(7)UINavigationController自定义导航按钮

    目录:[Swift]Xcode实际操作 本文将演示设置导航按钮的样式,以及设置导航标题区域的样式. import UIKit class FirstSubViewController: UIViewC ...

  4. springMVC容器加载源码分析

    springmvc是一个基于servlet容器的轻量灵活的mvc框架,在它整个请求过程中,为了能够灵活定制各种需求,所以提供了一系列的组件完成整个请求的映射,响应等等处理.这里我们来分析下spring ...

  5. Exadata中Infiniband交换机升级

    Infiniband交换机的软件补丁包,随着软件版本的不同,其发布方式也有所变化,从如下图表可以看出,1.3.3-2这个版本是一个分水岭,这个版本及以前的版本,补丁包是单独下载的,而之后的版本,inf ...

  6. An internal error occurred during: "Add Deployment". Container with path org.eclipse.jdt.launching.

    导入非本机项目出现这种错误,原因就是JDK版本不一致. 具体解决步骤如下: 右键项目名→Properties→JavaBuild Path→Libraries→选中JRE SystemLibrary[ ...

  7. Chapter10

    package scala import java.io.{PrintStream, PrintWriter}import java.util.Date import scala.util.loggi ...

  8. .db文件打开方式

    有时在工作中,数据库格式db后缀的格式,直接是打不开的,所以我这里使用了数据库管理工具,步骤如下 1. 在电脑安装 Navicat Premium,安装后在桌面生成图标,点击图标打开程序. 2.打开程 ...

  9. CUDA杂谈

    这一年都在编写CUDA的程序,用了很多优化的手段,发现大部分其实还是官方的指南里面的手段 https://docs.nvidia.com/cuda/cuda-c-best-practices-guid ...

  10. Maven的学习资料收集--(四)使用Maven构建Web项目-测试

    2014-08-04 23:21 2人阅读 评论(0) 收藏 编辑 删除   目录(?)[+]   [-] 在srcmainjava下新建一个Servlet 修改webxml 新建JSP 测试   在 ...