定义
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。
在接下来介绍的点分治中,从树的重心开始进行分治可以有效的避免出现链的极端情况,使得复杂度变为 $O(n^3)$
实现过程
使用一个 $\mathrm{son}$ 数组,记录以 $v$ 为根节点的子树中节点数目,在 dfs 时依次记录以 $v$ 为根节点下的各个子树的最大节点树(其父亲可以使用 $n-son[v]$ 得到),如果小于当前最大值,更新答案。
不要忘记将初始时 $\mathrm{root}$ (不要赋值为 $-1$,否则会下标越界,建议为 $0$ )对应的 $f$ 设置为无穷大,否则在更新子树时将无法更新!
代码
void getroot(int index,int father){
son[index] = 1; //计录子树大小
f[index] = 0; //初始化各子树最大节点数
for(int i=0;i<map[index].size();i++){
int v = map[index][i].to;
if(v!=father && !vis[v]){
getroot(v,index);
son[index] += son[v];
f[index] = max(f[index],son[v]);
}
}
f[index] = max(f[index],size-son[index]);
if(f[index] < f[root])
root = index; //更新
}