一类树上问题的总结

有时,我们会遇到这样的问题:
在一个树上选定一些点,每个点能覆盖一定范围的点……之类
比如:

通常,我们有两种做法:

方法一:我们对于每个点,考虑距离它最近的被选点

需要先证明一个显然的结论:对于每个i,以i为最近点的j是一个连通块。

换句话说,如果距离a的最近被选点为i,距离b的最近被选点也是i,那么a到b的路径上的点的最近被选点都是i。
考虑一条链:设Ax是链上第x个点,那么点y到Ax的距离fy(x)随x的增加,先下降,再上升。(这个显然)。
那么假设a到b路径上的c,最近点不是i而是j。
那么,\(dis(a,i)<dis(a,j),dis(c,i)>dis(c,j),dis(b,i)<dis(b,j)\)
就是说\(fi\)\(fj\)有两个交点。但这是不可能的。
所以,如果距离a的最近被选点为i,距离b的最近被选点也是i,那么a到b的路径上的点的最近被选点都是i一定成立。

这样,这样,我们设\(dp(i,j)\)表示i的最近点是j的状态。
(如果需要,再维护\(f(i)\)表示\(dp(i,j)\)的最小值。)
那么,对于i的每个儿子v,枚举它的最近点a,则转移到\(dp(v,a)\)
注意,如果\(j=a\),那么对于v来说,a已经选择过了,则转移时把选j的影响去掉。

由于形成连通块,正确性可以保证。

优点:适用范围较广,非常好写。
缺点:复杂度至少为\(O(n^2)\)

方法二:维护子树信息

对于每个子树,有2种信息:

猜你喜欢

转载自www.cnblogs.com/lnzwz/p/12146702.html