题意概述:

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

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

解析:

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

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

  

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

所以只需统计含割点个数小于等于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. E20170620-hm

    dump  n. 垃圾场; 仓库; 无秩序地累积;  vt. 倾倒; 倾销; 丢下,卸下; 摆脱,扔弃; terminate   vt. 结束; 使终结; 解雇; 到达终点站; adj. 结束的; d ...

  2. Vue 页面回退参数被当作字符串处理

    当时情景是这样的,我从A页面跳到B页面时会传一个Boolean类型的参数,当B跳到C,再从C返回B的时候,控制台打印发现参数还在,可是判断怎么都不起作用,后来发现,当页面返回的时候,默认将参数变成了字 ...

  3. 引水工程 Kruskal + Prim

    Kruskal题解 : 以案例输入为例 有五个缺水地区 , 这个个缺水地区之间建立联系的费用已经给出 并且之间水库的费用也已经给出 , 自己水库也已看为 是另一个 点 , 这样就有了 6 个点 , 这 ...

  4. 【洛谷2926/BZOJ1607】[USACO08DEC]Patting Heads拍头(筛法)

    题目: 洛谷2926 (截止至本博客发表时,BZOJ1607题面有误,正确题面请到洛谷2926查看) 分析: = 一句话题意:给定\(n\)个数\(\{a_i\}\),求对于每个\(a_i\)有多少个 ...

  5. struts2.1.6存在中文乱码的bug

    如题,后续版本中已解决:可以通过添加filter的方式解决.

  6. bootstrap 字体颜色 对齐方式

    一:字体代码:作用--颜色 1..text-muted:提示--浅灰色 2..text-primary:主要--蓝色 3..text-success:成功--浅绿色 4..text-info:     ...

  7. LinearLayout中间布局填充出现的问题

    线性布局如何中间填充,会挤掉他下面的布局,所以中间填充使用layout_weight属性.

  8. html5——:hover事件触发自己的:afert伪元素事件

    :hover事件触发自己的:afert伪元素事件中间是没有空格的

  9. C#——数据库的访问

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. [Windows Server 2012] WordPress安全设置方法

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:WordP ...