P3647 - 连珠线 题解

Portal

首先它从游戏开始到结束,是始终只有一个连通块的。对于连红边,那就直接连就可以了。对于连蓝边,我们首先需要找到一对有红边直接相连的点,然后拆散它们把新点插进去,然后仍然是一个连通块。稍微等价理解一下,发现其实就是一次连红边是从当前连通块伸出去一个点;而连蓝边肯定是一下就有两条,我们把这次蓝边所对应的红边与这次连蓝边看作一个整体,它可以看成从当前连通块伸出去一个长度为 \(2\) 的链,其中边是蓝色的。

于是我们可以钦定一个点为起始点,把给定树看作以它为根。那么显然在往下伸出去的时候,一口清伸出去的长度为 \(2\) 的链只可能是两端是爷孙关系,而不可能是兄弟关系了。好了!这样就很好 DP 了。

显然一个点只可能作为链的中心 \(0\sim 1\) 次。那么我们考虑 \(dp_{i,0/1}\) 表示子树 \(i\) 内的蓝边最大和,如果第二维为 \(1\) 的话表示 \(i\) 是一条链的中心(它下面有一条边与通向爸爸的边配对)。转移的话,如果为 \(0\) 那么所有儿子都必须是下面剩、边选或下面不剩、边不选,取个 \(\max\) 加起来即可,不需要有什么顾虑;为 \(1\) 的话就必须有且只有一个儿子是下面不剩、边选,找 \(\Delta\) 最大的那个减了加上即可。

然后套路的换根即可。这个求和可逆,不用烦;而求 \(\Delta\)\(\max\) 可以直接无脑的维护一个 set 添加删除即可,复杂度线性对数。然而发现在换根的过程中,一个点的 set 只会被连续删除 \(1\) 次元素,于是实时维护最大值和次大值即可线性,对应的也麻烦一点。

code

posted @ 2020-11-27 20:32  ycx060617  阅读(92)  评论(0编辑  收藏  举报