概念:
树的重心定义:
树的某个节点,当去掉该节点后,树的各个连通分量中,节点数最多的连通分量其节点数达到最小值
如图:
上图5就是重心,没有再优的点使得分割的最大连通块大小最小化
学此之前还是要掌握一下基础的树形dp
模板:
/*---code---*/
const int N = 2e5 + 5;
int n;
int siz[N],ans[N];
//siz[x] x的所有的子节点个数(包括x本身)
//ans[x] x所有子节点中的最大子节点个数
vector<int>g[N];
void dfs(int x,int pr){
siz[x]=1;
for(auto u:g[x]){
if(u==pr)continue;
dfs(u,x);
siz[x]+=siz[u];
ans[x]=max(ans[x],siz[u]);
}
ans[x]=max(ans[x],n-siz[x]);
//除去子节点的上方的节点个数
}
void solve(){
cin>>n;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
int res=ans[1];
for(int i=1;i<=n;i++){
res=min(res,ans[i]);
}
cout<<res;
}
样例:
输入:
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出:
4
代码解释:
实质就是统计各个子树的大小
取最大子树的大小
最大子树大小最小的节点就是树的重心
求子树的大小就用到了树形dp
dfs每个节点的子节点来统计siz大小
由于dfs是向下递归
那么节点上面的子树大小就是n-siz
最后统计最大子树的大小即可