虚树(Kindom and its Cities,消耗战)

本文详细介绍了虚树的概念和应用,通过一道模板题解析了如何使用虚树来优化树形DP。首先解释了如何通过删除节点使得关键点不相连的最小操作数,然后阐述了虚树的构建过程,包括实树、LCA计算和单调栈的应用。最后,通过实例展示了虚树的建树步骤,并给出了相关例题和代码模板。
摘要由CSDN通过智能技术生成

模板题引入

先来看一道模板题,CF上的。
这题的意思是给定一棵有 n n n个节点的树,树上有一些关键点( k e y key key)。接下来有 q q q组询问,每次给出 k i k_i ki k e y key key,要求删去一些点,使得这些 k e y key key不相连。要求删去的最少的点数。

模板题解析

第一眼看到这题,先想到的肯定是树形 d p dp dp。毕竟是在树上嘛。但是接下来看了一眼范围 1 ≤ n ≤ 100000 1\le n\le 100000 1n100000,而且 1 ≤ q ≤ 100000 1\le q\le 100000 1q100000。如果对于每个 q q q都跑一次完整的树,那么显然, O ( n ∗ q ) O(n*q) O(nq)一算就会 T L E TLE TLE
那么我们可以先不考虑这个,先想怎么 d p dp dp。很简单,运用贪心,分类。
如果当前节点是关键点,那么查询它是否有子儿子是关键点,如果有,那么显然连向这个子节点的链上需要被截断,否则就不用。
如果不是关键点,那么如果子树中有关键点并且多于 2 2 2个,那么显然,把当前节点删掉会最优,如果只有一个,那么留到后面和其他子树中的关键点分割更优。
因此,设当前节点是 x x x,它的儿子是 s o n son son,定义 d p [ i ] dp[i] dp[i]表示以 i i i为根的子树,使得所有的 k e y key key都不连通的最小删点个数, s i z [ i ] siz[i] siz[i]表示以 i i i为根的子树里 k e y key key的个数。则有:
i f ( x 是 k e y ) if(x是key) if(xkey)
d p [ x ] + = d p [ s o n ] ; \qquad dp[x]+=dp[son]; dp[x]+=dp[son];
i f ( s i z [ s o n ] ) a n s [ x ] + + ; \qquad\qquad if(siz[son]) ans[x]++; if(siz[son])ans[x]++;
e l s e else else
a n s [ x ] + = a n s [ s o n ] ; \qquad ans[x]+=ans[son]; ans[x]+=ans[son];
s i z [ x ] + = s i z [ s o n ] ; \qquad siz[x]+=siz[son]; siz[x]+=siz[son];
\qquad 在遍历完子节点后
i f ( s i z [ x ] > 1 ) \qquad if(siz[x]>1) if(siz[x]>1)
s i z [ x ] = 0 ; \qquad\qquad siz[x]=0; siz[x]=0;
a n s [ x ] + + ; \qquad\qquad ans[x]++;

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值