定义
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。
性质
- 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
- 找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。
- 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
- 以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。
- 把两棵树连起来,新树的重心必定在原来两棵树的重心连线的路径上。
应用
求树的重心模板
void getG(int u,int last){
int ret=0;
sz[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
getG(v,u);
ret=max(ret,sz[v]);
sz[u]+=sz[v];
}
ret=max(ret,n-sz[u]);
if(ret<szG){
szG=ret;
G=u;
}
}
\(O(n)\) 求一棵树中所有子树的中心
void dfs(int u,int last){
G[u]=u;
sz[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
dfs(v,u);
sz[u]+=sz[v];
}
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
if((sz[v]<<1)>sz[u]){
G[u]=G[v];
}
}
while(((sz[u]-sz[G[u]])<<1)>sz[u]){
G[u]=fa[G[u]];
}
}