关于树的重心

(由于本人太菜所以最近一直在补一些基础算法……)

求树的重心的基本思想就是从每个节点出发分别遍历一遍树,统计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;
	}
}

参考资料:李煜东《算法竞赛进阶指南》

原文地址:https://www.cnblogs.com/kma093/p/9747300.html