更换树根会导致树的某个性质发生改变,而题目需要我们分别求出以每一点为根时,对应的性质的值。
树的性质举例如下:
所谓换根法,是指将问题分为两步:
- 先任取一点为根建树,并求出此时的答案;
- 不断将当前树根的一个儿子变成树根、当前树根变成这个儿子的儿子(所谓换根),求出这种变化对答案的影响,直到遍历全树。
拿到题目,首先不考虑换根问题,先构造递归状态量$f(u)$(可能视情况要引入其他维度),对每个节点$u$求值后递归得到当前根节点的答案。 而“换根”这一操作可以通过引入cut
和link
两个互逆的过程来操作:
cut(u, v)
:当前v
是u
的儿子,我们把以v
为根的子树从以u
为根的切断,并统计切断操作对u
的答案产生的影响;link(u, v)
:将v
变成u
的儿子,即把以v
为根的子树连接到u
下面,并统计连接操作对u
的答案产生的影响。
而将原先的树根u
和它的一个儿子v
进行换根,就相当于先进行cut(u, v)
,再进行link(v, u)
操作。 以上就是换根法的主要精神。 一旦完成了解决问题的第一步,第二步的换根法应当是容易的。原因在于在第一步,我们在递归计算$f(u)$的每一步都在进行link
操作,由此可以容易地得到其逆过程cut
,进而得到换根操作。 但也有时我们可以通过数学关系直接求出换根操作的递推式,这时cut
和link
反而可能会比较麻烦。
CF219D
基础的换根操作题。
1 |
|
CF543D
甚至,在逆运算由于取模意义下乘法等原因的影响下不存在的时候,我们可以定义出可逆运算,如在取模乘法运算中定义0的个数。
1 |
|
CodeForces-708C
当我们需要维护的量是儿子中的最大值的时候,我们需要维护次大值来确保去掉一个儿子的贡献的时候可以恢复状态。下面这道题设f1[u]
和f2[u]
分别是以u
的所有儿子为根的子树中,子树大小的最大值和次大值分别在u
的哪个儿子中取到;g1[u]
和g2[u]
分别表示以u
为根的子树中,子树大小不超过n/2
的最大和次大子树的根节点,但注意最大和次大不同时取在u
的一个儿子里面,r1[u]
和r2[u]
就表示这两个节点是在u
的哪个儿子中取到的。
1 |
|