BZOJ2730 矿场搭建 解题报告 点双联通分量
题意概述:
一张有向图,在其中设置一些关键点(即题目中的逃生出口),使得删除任意一个点之后其余点都可以到达至少一个关键点。
问至少需要设置多少中关键点,有多少种设置方法。
解析:
首先,这道题要求删掉一个点,不难想到这道题与割点有关。其次,删掉一个点其他点仍然可以到达关键点就可以想到是点双联通分量。
但是,问题关键是,真的需要在每一个点双联通分量中都设置一个关键点吗?

答案是否定的,因为如果一个双联通分量连接了两个或两个以上的割点,一个割点被删掉那么还可以通过另外的割点到达某个关键点,如上图,红色点为割点,灰底色的边为割边
所以只需统计含割点个数小于等于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 矿场搭建 解题报告 点双联通分量的更多相关文章
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量
BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路 ...
- bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双
Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...
- 『Tarjan算法 无向图的双联通分量』
无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...
- 【UVA10972】RevolC FaeLoN (求边双联通分量)
题意: 给你一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,使得新的有向图强联通. 分析: 这题的解法还是很好想的.先用边双联通分量缩点,然后找新图中入度为0和为1的点,入度为0则ans ...
- lightoj 1300 边双联通分量+交叉染色求奇圈
题目链接:http://lightoj.com/volume_showproblem.php?problem=1300 边双连通分量首先dfs找出桥并标记,然后dfs交叉着色找奇圈上的点.这题只要求在 ...
- HDU5409---CRB and Graph 2015多校 双联通分量缩点
题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的. 不存在输出0 0 首先 若删除某一条边后存在多个联通分 ...
- poj2942(双联通分量,交叉染色判二分图)
题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1.2.总人数为奇数.3.有仇恨的骑士不能挨着坐.问有几个骑士不能和任何人形成任何的圆圈. 思路:首先 ...
- 大白书中无向图的点双联通分量(BCC)模板的分析与理解
对于一个无向图,如果任意两点至少存在两条点不重复(除起点和终点外无公共点)的路径,则这个图就是点双联通. 这个要求等价于任意两条边都存在于一个简单环(即同一个点不能在圈中出现两次)中,即内部无割点. ...
随机推荐
- codeforces educational round 25
A 出题人不给样例解释...具体程序 #include<bits/stdc++.h> using namespace std; int n; ]; int main() { scanf() ...
- cropbox
今天给大家分享一款基于jQuery头像裁剪插件cropbox,这是一款简单实用的jQuery头像在线裁剪插件.该插件适用于适用浏览器:IE8.360.FireFox.Chrome.Safari.Ope ...
- Akka源码分析-Remote-收发消息UL图
- 观察者模式-C#实现
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 观察者模式有四个角色:抽象主题.具体主题.抽象观察者.具体观察者. 抽象主题:把所有观察者对象 ...
- 康少带你玩转CSS-1
什么是CSS? 层叠样式表(假如HTML是一个人的话,css就是一个人的装饰品,比如裙子,衣服口红) 用来干什么的 设置标签样式的 css注释 单行注释/**/ 多行注释 /* */ 语法结构 三种引 ...
- ACM_三元一次函数解法(克莱姆法则)
三元一次函数 Time Limit: 2000/1000ms (Java/Others) Problem Description: 计算三元一次函数..如图 Input: EOF,先输入n,表示样例个 ...
- ACM_圆的面积
圆的面积 Time Limit: 2000/1000ms (Java/Others) Problem Description: AB是圆O的一条直径,CD.EF是两条垂直于AB的弦,并且以CD为直径的 ...
- C# 利用反射进行类型转换
/// <summary> /// 父类转子类 /// </summary> /// <typeparam name="TParent">< ...
- jQuery——jQuery选择器
基本选择器 # Id选择器 $(“#btnShow”)选择id为btnShow的一个元素 . 类选择器 $(“.liItem”)选择含有类liItem的所有元素 ele 标签选择器 $(“li”)选择 ...
- 使用LocalDB部署Asp.Net MVC网站时遇到的问题
首先一句话介绍LocalDB.LocalDB是SQLServer的文件数据库,类似于SQLite.它拥有SQLServer的绝大部分功能,简单易用.但部署LocalDB到生产系统是不推荐的.本文部署是 ...