题意概述:

  一张有向图,在其中设置一些关键点(即题目中的逃生出口),使得删除任意一个点之后其余点都可以到达至少一个关键点。

  问至少需要设置多少中关键点,有多少种设置方法。

解析:

  首先,这道题要求删掉一个点,不难想到这道题与割点有关。其次,删掉一个点其他点仍然可以到达关键点就可以想到是点双联通分量。

  但是,问题关键是,真的需要在每一个点双联通分量中都设置一个关键点吗?

  

答案是否定的,因为如果一个双联通分量连接了两个或两个以上的割点,一个割点被删掉那么还可以通过另外的割点到达某个关键点,如上图,红色点为割点,灰底色的边为割边

所以只需统计含割点个数小于等于1的块数就是最少的关键点个数,如此,则放置关键点的方案数为各个被统计的块(割点数小于等于1的块)的点的个数的乘积,当然,若只找到了一个满足条件的块,那最少关键点数为2,方案数为(令n为点的个数):  n*(n-1)/2.

需要注意的是这道题的数据规模:有500条边,但是并没有对点的编号的说明,所以点的标号可以是任意的,故此题建议离散化,但是我还是偷了个懒,因为数据中的点好像不超过50000

代码如下:

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector> using namespace std; //#define File
//#define Debug struct Edge
{
int to;
int next;
}e[]; int n,cnt,cnt_blocks,bcc_cnt,top,Ans,kase;
int p[],dfn[],nbcc[]; long long Sum; pair<int,int> st[];
vector<int> bcc[]; bool cut[]; inline void Add_edge(const int x,const int y)
{
e[++cnt].to=y;
e[cnt].next=p[x];
p[x]=cnt;
return ;
} int Tarjan(const int S,const int fa)
{
int child,lowu,lowv,v,i; dfn[S]=lowu=++cnt_blocks;
child=; for(i=p[S];i;i=e[i].next)
{
v=e[i].to;
if(!dfn[v])
{
st[++top]=make_pair(S,v);
child++;
lowv=Tarjan(v,S);
lowu=min(lowv,lowu);
if(lowv>=dfn[S])
{
cut[S]=true;
bcc_cnt++;
bcc[bcc_cnt].clear();
while(true)
{
if(nbcc[st[top].first]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(st[top].first);
nbcc[st[top].first]=bcc_cnt;
}
if(nbcc[st[top].second]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(st[top].second);
nbcc[st[top].second]=bcc_cnt;
} if(st[top].first==S && st[top].second==v)
{top--;break;}
top--;
}
}
}
else if(dfn[v]<dfn[S] && v!=fa)
{
st[++top]=make_pair(S,e[i].to);
lowu=min(lowu,dfn[v]);
}
} if(fa< && child==)cut[S]=false;
return lowu;
} inline void Init()
{
/*int n,cnt,cnt_blocks,bcc_cnt,top,Ans,kase;
int p[51000],dfn[51000],nbcc[51000]; long long Sum; pair<int,int> st[51000];
vector<int> bcc[1100]; bool visited[51000],cut[51000];*/
cnt=cnt_blocks=bcc_cnt=top=Ans=;
Sum=;
memset(p,,sizeof(p));
memset(dfn,,sizeof(dfn));
memset(nbcc,,sizeof(nbcc));
memset(cut,,sizeof(cut));
for(int i=;i<=;++i)
bcc[i].clear();
memset(st,,sizeof(st));
return ;
} int main()
{
#ifdef File
freopen("2730.in","r",stdin);
#ifndef Debug
freopen("2730.out","w",stdout);
#endif
#endif int i,j,x,y,cut_cnt; while(~scanf("%d",&n) && n)
{
Init();
for(i=;i<=n;++i)
{
scanf("%d%d",&x,&y);
Add_edge(x,y);
Add_edge(y,x);
} for(i=;i<=n;++i)
{
if(!dfn[i])Tarjan(i,-);
} for(i=;i<=bcc_cnt;++i)
{
cut_cnt=;
for(j=;j<(int)bcc[i].size();++j)
{
if(cut[bcc[i][j]])cut_cnt++;
}
if(cut_cnt==)
{
Ans++;
Sum*=(long long)(bcc[i].size()-cut_cnt);
}
} if(bcc_cnt==)
{
Ans=;
Sum=bcc[].size()*(bcc[].size()-)/;
} printf("Case %d: %d %lld\n",++kase,Ans,Sum);
} #ifdef File
fclose(stdin);
#ifndef Debug
fclose(stdout);
#endif
#endif return ;
}

BZOJ2730 矿场搭建 解题报告 点双联通分量的更多相关文章

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

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

  2. BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量

    BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路 ...

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

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

  4. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

  5. 【UVA10972】RevolC FaeLoN (求边双联通分量)

    题意: 给你一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,使得新的有向图强联通. 分析: 这题的解法还是很好想的.先用边双联通分量缩点,然后找新图中入度为0和为1的点,入度为0则ans ...

  6. lightoj 1300 边双联通分量+交叉染色求奇圈

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1300 边双连通分量首先dfs找出桥并标记,然后dfs交叉着色找奇圈上的点.这题只要求在 ...

  7. HDU5409---CRB and Graph 2015多校 双联通分量缩点

    题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的. 不存在输出0 0 首先 若删除某一条边后存在多个联通分 ...

  8. poj2942(双联通分量,交叉染色判二分图)

    题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1.2.总人数为奇数.3.有仇恨的骑士不能挨着坐.问有几个骑士不能和任何人形成任何的圆圈. 思路:首先 ...

  9. 大白书中无向图的点双联通分量(BCC)模板的分析与理解

    对于一个无向图,如果任意两点至少存在两条点不重复(除起点和终点外无公共点)的路径,则这个图就是点双联通. 这个要求等价于任意两条边都存在于一个简单环(即同一个点不能在圈中出现两次)中,即内部无割点. ...

随机推荐

  1. POJ 1056 IMMEDIATE DECODABILITY Trie 字符串前缀查找

    POJ1056 给定若干个字符串的集合 判断每个集合中是否有某个字符串是其他某个字符串的前缀 (哈夫曼编码有这个要求) 简单的过一遍Trie就可以了 #include<iostream> ...

  2. tinymce 富文本编辑器 编写资料

    tinymce官方文档: 粘贴图片插件 博客搬运地址 使用Blob获取图片并二进制显示实例页面 tinymce自动调整插件 是时候掌握一个富文本编辑器了——TinyMCE(1) XMLHttpRequ ...

  3. 原生方式实现Ajax技术

    一:什么是Ajax? Ajax:异步的JavaScript和XML,用于完成网页局部刷新功能(修改少量数据只用局部刷新,不用再整个网页重新加载): XML的作用:1.是用于数据传输,但现在都在使用JS ...

  4. centos7离线安装rabbitmq

    准备工作 一台centos7的机器 erlang-21.3.8.2 RabbitMQ 3.7.15 socat-1.7.3.2-2.el7.x86_64.rpm 开始安装 登录centos ,把上面的 ...

  5. redis+php实现秒杀

    使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用(mysql事务在高并发下性能下降很厉害,文件锁的方式也是) 先将商品库存如队列 1 2 3 4 5 6 7 ...

  6. Java继承体系中this的表示关系

    在继承关系下,父类中的this关键字并不总是表示父类中的变量和方法.this关键字的四种用法如前文所述,列举如下. 1) this(paras…); 访问其他的构造方法 2) this.xxx; 访问 ...

  7. 个人作业——Alpha项目测试

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/ 这个作业要求在哪里 https://edu.cnbl ...

  8. 【译】x86程序员手册00 - 翻译起因

    从上一次学习MIT的操作系统课程又过去了一年.上次学习并没有坚持下去.想来虽有种种原因,其还在自身无法坚持罢了.故此次再鼓起勇气重新学习,发现课程都已由2014改版为2016了.但大部分内容并没有改变 ...

  9. Centos6.6 安装基于系统认证的vsftp服务

    一.介绍 vsftp是一款文件服务器软件,在文件共享,代码更新,文件备份中也是经常用到,以下是基本安装环境: 1)CentOS6.6 2)vsftpd-2.2.2 二.安装 $ yum install ...

  10. CWnd* pParent

    Dlg(CWnd* pParent = NULL)的意思是:构造函数.创建对象时第一个调用的地方.CWnd* pParent=NULL是构造的参数,可以不传入,默认为NULL 构造函数(constru ...