(由于本人太菜所以最近一直在补一些基础算法……)
求树的重心的基本思想就是从每个节点出发分别遍历一遍树,统计max_part,其中能够使得max_part最小的就是树的重心
另外:一棵有根树至多有两个重心,这个结论好像有些题可以用(比如BZOJ4337,不过那个数据太水只有50(什么暴力乱搞都能过去),但据高三的DZYO神仙说数据可以出到1e6)
大部分的解释都在代码里面(其实没有什么好解释的……我解释了下各个变量的意思)
/*
树的重心定义:对于一个树中节点x,当我们删去它时会将原来的树分割成若干个不相连的部分,其中每个部分都是一颗子树。
设max_part表示这些部分中最大的一棵子树,若删去节点x能够使得max_part最小,则称这个点为树的重心
*/
void Dfs(int x){
/*
v[i]:遍历的时候打标记
size[i]:删去x后以i为根的子树的大小
max_part:删去x之后大小最大的子树的大小
pos:搜索到现在使得max_part最小的节点
ans:搜到现在max_part的最小值
*/
v[x]=1; size[x]=1;
int max_part=0;
for(register int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(v[y])continue;
Dfs(y);
size[x]+=size[y];
max_part=max(max_part,size[y]);
}
max_part=max(max_part,n-size[x]);
if(max_part<ans){
ans=max_part;
pos=x;
}
}
参考资料:李煜东《算法竞赛进阶指南》