一个树上每一个点都有一个组别,求相同组别的点对相差的最大距离。可以叫这题为“部分树的直径”
有一个结论:对于任意一个组别,深度最大的点一定在答案的点对里。
审视一下这个证明是如何分类的,对于LCA的部分,显然是通过讨论\(y\)是不是\(z\)的祖先来完成的;之后是通过讨论是否是子树来进行的
所以,对于不同组别,我们只需要求出深度最大的点即可,之后在跑一遍LCA即可,均摊下来\(O(N)\)
然而,这道题目还有更简单的做法
既然是与直径有关,我们回想一下BFS求树的直径是怎么求的
回想完后,我们回到这道题目,对于一个组别,我们把有关这个组别的极大子树(即度数为\(1\)的点都是由这个组别的点构成的,而且这个组别的所有点都在这个子树里面)提出来,如果我们能够对每个组别的极大子树求出直径,那么显然就是答案(因为极大子树的边界都是这个组别的点,而极大子树的直径又一定是以边界作为端点的)
我们模仿BFS的过程,首先求出每个组别直径的端点,只需要在dfs遍历原树的时候,对于当前点:
如果当前点所在组别没被标记,则标记,并把当前点作为其组别的代表
如果当前点所在组别已经被标记,则用当前点与其组别代表求距离,并记录下其组别距离的最大值
一遍dfs完了之后,我们就相当于对每个极大子树求出了一个直径的端点,之后再dfs一遍,并模仿类似过程就可以解决问题了
标签:子树,组别,Cow,别的,dfs,端点,Politics,直径 From: https://www.cnblogs.com/dingxingdi/p/18011789