【算法】树的重心

树的重心,也叫树的质心。即树的一个点,以它为根时所有子树最大子树最小。删去重心后,生成的多棵树尽可能平衡。

在树的点分治中通常要用到。

性质

  1. 树中所有点到某个点的距离和中,到重心的距离和是最短的。如果有两个重心,它们的距离和相等。
  2. 把两棵树用一条边相连,新的树的重心在原来两棵树的重心的连线上。
  3. 一棵树添加或删除一个节点后,树的重心最多只移动一条边的位置。
  4. 一棵树最多有两个重心,且相邻。

求法

先任意取一个点作为根,在这棵树上求出每一个子树的大小,对每个结点求它的各个子树的最大大小,若 v 是 u 的子树,那么 maxsizeu=max{max(sizev),nsizeu}maxsize_u=max\{max(size_v),n-size_u\}。dfs 一遍 O(n) 求出。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=1e5+10;
int n;

//Edge
struct Edge
{
	int to, next;
}e[N];
int hn, h[N];
void add(int u, int v)
{
	e[++hn].to=v; e[hn].next=h[u];
	h[u]=hn;
}

//weight
int sz[N], pos, minz;

void dfs(int u, int fa)
{
	sz[u]=1;
	int maxz=0;
	for(int p=h[u]; p; p=e[p].next)
	{
		int v=e[p].to;
		if(v==fa) continue;
		dfs(v,u);
		sz[u]+=sz[v];
		maxz=max(maxz,sz[v]);
	}
	maxz=max(maxz,n-sz[u]);
	if(maxz<minz)
	{
		pos=u;
		minz=maxz;
	}
}

int main()
{
	scanf("%d", &n);
	for(int i=1, u, v; i<n; ++i)
	{
		scanf("%d%d", &u, &v);
		add(u,v); add(v,u);
	}
	minz=n;
	dfs(1,0);
	printf("%d", pos);
	return 0;
}

资料来源:
百度百科

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章