题意概述:

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

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

解析:

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

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

  

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

所以只需统计含割点个数小于等于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. JSP-Runoob:JSP 过滤器

    ylbtech-JSP-Runoob:JSP 过滤器 1.返回顶部 1. JSP 过滤器 JSP 和 Servlet 中的过滤器都是 Java 类. 过滤器可以动态地拦截请求和响应,以变换或使用包含在 ...

  2. yum -y --downloadonly --downloaddir=/root/ruiy update

    依赖关系解决 ============================================================================================= ...

  3. css link的事件与顺序

    创建: 2017/10/26 link:连接平常的状态 visited:连接被访问过之后 hover:鼠标放到连接上的时候 active:连接被按下的时候

  4. Sara Cope关于text-shadow的介绍

    作者:Sara Cope p { text-shadow: 1px 1px 1px #000; } 你可以通过逗号“,”应用多个文本阴影. p { text-shadow: 1px 1px 1px # ...

  5. 免费开源ERP成功案例分享:化学之家通过Odoo实现工业互联网转型

    本文来自<开源智造Odoo客户成功案例采访实录>的精选内容章节.请勿转载.欢迎您反馈阅读意见. 客户地区:江苏常州 客户名称:化学之家(中外合资) 所属行业:化工制造(工业) 实施模块:销 ...

  6. 关于二分查找 使用 lower_bound

    在寻找单调递增最长自序列 , 的时候能不能确认出来哪个是单调递增最长自序列  ?  我的想法是 if(location>=num) dp[location]=b; 这样的 , 基于http:// ...

  7. celery定时执行ansible api返回为空的问题

    有两种方法解决这个问题,就是关闭assert:1.在celery 的worker启动窗口设置export PYTHONOPTIMIZE=1或打开celery这个参数-O OPTIMIZATION2.注 ...

  8. [ ZJOI 2006 ] Trouble

    \(\\\) \(Description\) 有\(N\)个人的环,每个人需要至少\(x_i\)种不同的物品,并且要求任意相邻的两人都没有相同的物品,求最少需要多少种物品. \(N\in [0,2\t ...

  9. Python--10、进程知识补充

    守护进程 基于进程启动的子进程,会和主进程一起结束.主进程结束的依据是程序的代码执行完毕. #创建守护进程p=Process(task) p.daemon = True p.start() 子进程需要 ...

  10. jsp之认识 servlet (基础、工作原理、容器请求处理)

    Tomcat 的安装: eclipse 需要自行安装tomcat,这是web 项目运行的服务器.如果用的是MyEclipse,里面自带tomcat,方便清除部署垃圾,利于项目运行. Tomcat的安装 ...