【算法】树的重心

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

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

性质

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

求法

先任意取一个点作为根,在这棵树上求出每一个子树的大小,对每个结点求它的各个子树的最大大小,若 v 是 u 的子树,那么 m a x s i z e u = m a x { m a x ( s i z e v ) , n − s i z e u } maxsize_u=max\{max(size_v),n-size_u\} maxsizeu=max{max(sizev),nsizeu}。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;
}

资料来源:
百度百科

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值