【算法简介】
虚树就是对于一个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]消耗战
【例题2】CF809E Surprise me!

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

被折叠的 条评论
为什么被折叠?



