CodeForces - 708C Centroids

Posted on 2022-11-10 20:41  Capterlliar  阅读(39)  评论(0编辑  收藏  举报

题意:给出一棵有n个结点的树,对于每一个结点,如果任意删除一条边后再任意添加一条边能使这个结点成为这棵树的重心,则输出1;反之输出0。

解:重心的特点:以重心为根节点时,其最大子树的节点数最小,且每个子树大小不超过n/2。考虑更换一条边的操作,如果这个结点当根节点时,有一棵子树大小超过n/2,那么砍掉这颗子树不超过n/2的最大子树,并把它接到根节点来。如果此时最大子树仍超过n/2,那么这个结点不可能成为重心。

对于每一个结点都O(n)地判断一遍显然是会超时的,考虑类似于换根的操作。先以随便一个结点作为根,dfs出每个结点的子树大小。然后再dfs一遍,进入一个结点时,其父结点和之前的结点为当前结点的子树。递归进入的时候记录之前小于等于n/2的最大子树和次大子树(当进入的结点在最大子树中时,应该传次大子树的值)。然后比较判断。

cf官方题解的做法更简洁。一开始以树的重心为根进行dfs,这样只要考虑之前结点形成的子树。已知当前子树外其他结点加起来大于等于n/2,因此又只要考虑原来第一和第二大的子树。这样事情就很简单了。