luogu3225 [HNOI2012]矿场搭建
题目大意
给出一个有$n(n\leq 500)$个节点的无向图,一个满足条件的点集$V$会使得对于图中的每一个节点$u$,满足路径起点为$u$终点$v\in V$的路径集合$P_u$中总存在至少两条路径$p_1,p_2$,使得该两条路径除了起点外没有交集(终点也不同)。输出$|V|$的最小值,以及$|V|$最小时$V$的种类数。
题解
对于一个点双连通分量中的任意一对点都有两条路径到达对方,所以我们从点双连通分量入手。
特殊情况:当一个点双连通分量中没有割点时,根据题目要求,这个点双连通分量中需要有两个点属于$V$。
若把所有点双连通分量缩点形成一棵树,那么树必定会有叶子节点。所以我们考虑当一个点双连通分量有一个割点时该怎么办。考虑到去掉的点是割点的情况,每个叶子双联通分量内必需有一个点$t$属于$V$;若去掉的点位于所在连通分量以外的部分,双连通分量内的点都与$t$连通;若去掉的点在双连通分量以内且不属于割点,那么双连通分量内的其它点到割点必然存在一条路径,而割点必然与其它叶子双连通分量相连通,那里有属于$V$的点。因此,所有叶子双连通分量内必须有且只有一个点属于$V$。
若一个点双连通分量不是叶子,那么无论去掉哪个点,这个点双连通分量总与叶子连通,那里有属于$V$的点,所以这里的点双连通分量没有属于$V$的点。
关于根节点的特判,将根节点所在的点双连通分量记录下来,在Dfs外面对根节点进行特殊处理即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <cassert>
using namespace std; const int MAX_NODE = 510; struct Node
{
vector<Node*> Next;
int DfsN, Low;
bool IsCut;
}_nodes[MAX_NODE];
stack<Node*> St; struct Block
{
int NodeCnt, CutCnt;
}_blocks[MAX_NODE];
int BlockCnt;
int DfsCnt;
vector<Block*> RootIn; void DeStack(Node *end, Node *add)
{
BlockCnt++;
Node *temp;
do {
temp = St.top();
St.pop();
_blocks[BlockCnt].NodeCnt++;
_blocks[BlockCnt].CutCnt += temp->IsCut;
} while (temp != end);
_blocks[BlockCnt].NodeCnt++;
_blocks[BlockCnt].CutCnt += add->IsCut;
} int Dfs(Node *cur)
{
cur->Low = cur->DfsN = ++DfsCnt;
St.push(cur);
int cnt = 0;
for (int i = 0; i < cur->Next.size(); i++)
{
if (!cur->Next[i]->DfsN)
{
Dfs(cur->Next[i]);
cur->Low = min(cur->Low, cur->Next[i]->Low);
if (cur->Next[i]->Low >= cur->DfsN)
{
cnt++;
if (cur != _nodes + 1)
cur->IsCut = true;
DeStack(cur->Next[i], cur);
if (cur == _nodes + 1)
RootIn.push_back(_blocks + BlockCnt);
}
}
else
cur->Low = min(cur->Low, cur->Next[i]->DfsN);
}
return cnt;
} void Clear()
{
for (int i = 1; i < MAX_NODE; i++)
{
_nodes[i].Low = _nodes[i].DfsN = _nodes[i].IsCut = 0;
_nodes[i].Next.clear();
_blocks[i].CutCnt = _blocks[i].NodeCnt = 0;
}
RootIn.clear();
BlockCnt = 0;
DfsCnt = 0;
} int main()
{
int totEdge, caseCnt = 0;
while (scanf("%d", &totEdge) && totEdge)
{
Clear();
for (int i = 1; i <= totEdge; i++)
{
int u, v;
scanf("%d%d", &u, &v);
_nodes[u].Next.push_back(_nodes + v);
_nodes[v].Next.push_back(_nodes + u);
}
int rootBlockCnt = Dfs(_nodes + 1);
if (rootBlockCnt > 1)
{
_nodes[1].IsCut = true;
for (int i = 0; i < RootIn.size(); i++)
RootIn[i]->CutCnt++;
}
while (!St.empty())
St.pop();
int exitCnt = 0;
long long solCnt = 1;
for (int i = 1; i <= BlockCnt; i++)
{
if (_blocks[i].CutCnt == 0)
{
assert(BlockCnt == 1);
exitCnt = 2;
solCnt = (long long)_blocks[i].NodeCnt * (_blocks[i].NodeCnt - 1) / 2;
}
else if (_blocks[i].CutCnt == 1)
{
exitCnt++;
solCnt *= (_blocks[i].NodeCnt - _blocks[i].CutCnt);
}
}
printf("Case %d: %d %lld\n", ++caseCnt, exitCnt, solCnt);
}
return 0;
}
luogu3225 [HNOI2012]矿场搭建的更多相关文章
- bzoj2730 [HNOI2012]矿场搭建 (UVAlive5135 Mining Your Own Business)
2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1147 Solved: 528[Submit][Statu ...
- BZOJ 2730: [HNOI2012]矿场搭建( tarjan )
先tarjan求出割点.. 割点把图分成了几个双连通分量..只需dfs找出即可. 然后一个bcc有>2个割点, 那么这个bcc就不用建了, 因为一定可以走到其他救援出口. 只有一个割点的bcc就 ...
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 【BZOJ】2730: [HNOI2012]矿场搭建【Tarjan找割点】【分联通块割点个数】
2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3230 Solved: 1540[Submit][Stat ...
- Tarjan 点双+割点+DFS【洛谷P3225】 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- [luoguP3325][HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- [BZOJ2730][HNOI2012]矿场搭建 点双 割点
2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2852 Solved: 1344[Submit][Stat ...
- 【BZOJ2730】[HNOI2012]矿场搭建 Tarjan
[BZOJ2730][HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处. ...
- BZOJ 2730:[HNOI2012]矿场搭建(割点+连通块)
[HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖 ...
随机推荐
- 【1】Jdk1.8中的HashMap实现原理
HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. 内部实现 ...
- Android基础TOP3:Activity的线性,相对,帧和表格布局的概括
线性布局 LinearLayout: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...
- Robomongo 0.9.0 连接mongo数据库时,提示连接失败 的解决方案
Robomongo 0.9.0 连接mongo数据库时,提示连接失败.(IP和端口号确定是对的) 基本注意点: 1.mongodb服务打开,打开时,指定端口号,默认为27017,使用默认值,则不用指定 ...
- Less——less基本安装
1.下载node.js 我们需要NodeJ运行LESS示例. 要下载NodeJ,请打开链接https://nodejs.org/en/ 2.node.js安装是否正确 在cmd中输入lessc -v, ...
- html5——多媒体(二)
基本方法 load() //重新加载视频 play() //播放 pause() //暂停 基本属性 currentTime //视频播放的当前进度. duration //视频的总时间 paused ...
- 类QQ账号生成阐述
具体需求如下: 数字账号从60000到9999999999(类似qq号一样的东东) 用户获取数字账号为随机分配,也可递加分配,需要符合如下规则 特殊账号需要保留,不能分配给用户,比如:112233(连 ...
- 使用码云gitee.com托管代码
1.新建项目 可以看到团队资源管理器是这样的,已经在本地有存储库,所有更改可以保存本地 2.在码云上新建项目 项目名称必填,其它项根据情况填写 3.复制项目地址关联到本地存储库 填写码云的项目地址,发 ...
- HDU_2203_KMP入门
亲和串 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- Origin C调用GSL
GSL (GNU Scientific Library, http://www.gnu.org/software/gsl/)是C.C++的数值算法库,提供了范围宽广的数学程序,包括随机数字生成器.数理 ...
- python开发 面试题
一.简述列表与元组的区别 答: 元组tuple与列表List相同点 元组tuple与列表List都是序列类型的容器对象,可以存放任何类型的数据.支持切片.迭代等操作. 元组tuple与列表List区别 ...