Codeforces 613D(虚树)

题目大意

链接
给定一棵树,每次给定一些点,求最少要阻断多少点使得这些点之间两两之间无法通行。其中不能阻断给定点,无解输出-1.

分析

虚树上贪心/DP即可。

虚树

由于在树上有可能有很多点根本就不需要用,所以我们要把这些点提出来单独组成一棵树,减少了大量运算。

一般来说我们要提出的点是所有的点和这些点之间两两LCA的点,然而K个点LCA的点仅仅有K-1个,也就是按照DFS序排序之后相邻的点之间LCA即可。

我挑了一种比较好理解和易于自己实现的写法。
首先获得原树,然后遍历之后得到DFS序,并且拥有一个办法求LCA,求出DFS序,求出每个点所在子树的时间戳范围。
对于每一组数据我们有如下操作:

  1. 获取结点,按照DFS序排序,相邻结点之间获取它们的LCA,再把所有结点按照DFS序排序,去重。
  2. 弄一个栈,先加入DFS序最小的,它也就是整个虚树的根。
  3. 依次加入结点,如果当前结点不在栈顶结点的子树内,就弹出栈顶结点。然后连接栈顶元素和当前元素,把当前元素入栈。

好了虚树就构建好了。

说几个注意的点:

  • 建立虚树的时候是个有根树,可以不向根的方向连边,因此遍历的时候不用判断父亲结点。
  • 边和其它数据的还原最好利用我们得到的结点逐个还原,因为原树太大了。
  • 注意排序的时候要加cmp函数,但是unique的时候不要加。

代码

#include<cmath>
#include<queue>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=3e5+105,inf=1e6,oo=18;
int n,m;
int dfn,l[maxn],r[maxn],dep[maxn],fa[maxn]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值