树的重心
概念
如果在树中选择某个节点并删除,这棵树将分为若⼲棵⼦树,统计⼦树节点数并记录最⼤值。取遍树
上所有节点,使此最⼤值取到最⼩的节点被称为整个树的重⼼。
性质
树的重⼼如果不唯⼀,则⾄多有两个,且这两个重⼼相邻。
• 以树的重⼼为根时,所有⼦树的⼤⼩都不超过整棵树⼤⼩的⼀半。
• 树中所有点到某个点的距离和中,到重⼼的距离和是最⼩的;如果有两个重⼼,那么到它们的距离
和⼀样。
◦ 推论⼀:即使边权不为1 ,只要没有负边权,不影响各点到重⼼的距离和最⼩;
◦ 推论⼆:即使边权和点权都不为1 ,只要没有负边权,不影响各点到重⼼的距离和最⼩。
实现
#include <iostream>
#include <vector>
using namespace std;
const int N = 5e4 + 10;
int n;
vector<int> edges[N];
int f[N]; // f[x] 表⽰:以 x 为根的⼦树的⼤⼩
int r1, r2, ret = N;
void dfs(int x, int fa){
f[x] = 1;
int m = 0; // 把 x 删除之后,所有⼦树的最⼤值
for(auto y : edges[x]){
if(y == fa) continue;
dfs(y, x);
m = max(m, f[y]);
f[x] += f[y];
}
m = max(m, n - f[x]);
if(m < ret){
r1 = x, r2 = 0;
ret = m;
}
else if(m == ret){
r2 = x;
}
}
int main(){
cin >> n;
for(int i = 1; i < n; i++){
int a, b; cin >> a >> b;
edges[a].push_back(b);
edges[b].push_back(a);
}
dfs(1, 0);
if(r1 > r2) swap(r1, r2);
if(r1 && r2) cout << r1 << " " << r2 << endl;
else cout << r2 << endl;
return 0;
}

浙公网安备 33010602011771号