虚树

本文介绍了虚拟树的概念,主要用于优化涉及少数关键点的LCA(最近公共祖先)查询。通过预处理LCA和DFS序,使用增量算法构建虚拟树。在每个询问中,根据DFS序依次加入关键点,并维护一个栈,根据栈内的节点和询问点的LCA关系调整虚树结构。文章列举了一个CF比赛题目作为具体应用案例,展示了如何在实际问题中运用虚拟树解决树形结构的查询问题。

【算法简介】

虚树就是对于一个n个节点的树T,我构造出一个新的树T'使得其节点数最少,包含指定的一些节点(关键点)和它们的lca

一般出现关键点的数目较少且有较多次询问时,我们就要利用到虚树了

 

【构造方法】

对于整棵树预处理lca和dfs序,利用增量算法构造

对于一个询问涉及到了k个关键点,我们按照dfs序依次加入

建立虚树时我们需要开一个栈st[],用于记录原路径上按照之前加入的询问点要加入虚树的那些点,按照深度从小到大储存

每次加入一个节点x,计算出x,st[top]的lca,如果这个lca=st[rop]也就是说x是st[top]的子树内节点,那么直接st[++top]=x即可

如果lca!=st[top],那么我们就需要不断弹出st[top]直到dep[st[top-1]]<dep[lca],每次弹出st[top]的时候,都要给st[top-1]和st[top]连上一个边

如果弹完之后仍不满足lca=st[top]那么我们就需要把lca加进栈内

插完所有的点以后要全部弹栈

这种方法的正确性显然,手玩一下就好了

时间复杂度O(∑(klogk+klogn))

【具体应用】

直接看一道例题吧

【例题1】CF613D Kingdom and its Cities

首先特判掉无解的情况,也就是选了x和fa[x]的情况

然后我们可以建立虚树,给指定的k个点设置点权为1(为了区分lca)

设f[x]为以x为子树的答案,g[x]为这个点及其子树内是否有需要被割的点

考虑这个点是不是关键点,如果是原来给定的点,f[x]+=g[xson],也就是让他的所有需要被断开的儿子都断开

如果这个点不是关键点,那么我们考虑如果他有多个儿子都需要被断开,那就把这个点断开f[x]+=1,如果只有一个就让g[x]=1,向上传递等待被断
sol.

【练习1】P2495 [SDOI2011]消耗战

sol.

【例题2】CF809E Surprise me!

sol.

其他习题

【练习2】P4103 [HEOI2014]大工程

【练习3】P7409 SvT

【练习4】P3233 [HNOI2014]世界树

【练习5】CF809E Surprise me!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值