Cow Politics G

一个树上每一个点都有一个组别,求相同组别的点对相差的最大距离。可以叫这题为“部分树的直径”

有一个结论:对于任意一个组别,深度最大的点一定在答案的点对里。

审视一下这个证明是如何分类的,对于LCA的部分,显然是通过讨论\(y\)是不是\(z\)的祖先来完成的;之后是通过讨论是否是子树来进行的

所以,对于不同组别,我们只需要求出深度最大的点即可,之后在跑一遍LCA即可,均摊下来\(O(N)\)

然而,这道题目还有更简单的做法

既然是与直径有关,我们回想一下BFS求树的直径是怎么求的

回想完后,我们回到这道题目,对于一个组别,我们把有关这个组别的极大子树(即度数为\(1\)的点都是由这个组别的点构成的,而且这个组别的所有点都在这个子树里面)提出来,如果我们能够对每个组别的极大子树求出直径,那么显然就是答案(因为极大子树的边界都是这个组别的点,而极大子树的直径又一定是以边界作为端点的)

我们模仿BFS的过程,首先求出每个组别直径的端点,只需要在dfs遍历原树的时候,对于当前点:

如果当前点所在组别没被标记,则标记,并把当前点作为其组别的代表

如果当前点所在组别已经被标记,则用当前点与其组别代表求距离,并记录下其组别距离的最大值

一遍dfs完了之后,我们就相当于对每个极大子树求出了一个直径的端点,之后再dfs一遍,并模仿类似过程就可以解决问题了

posted @ 2024-02-08 14:27  最爱丁珰  阅读(1)  评论(0编辑  收藏  举报