树的重心定义
1.找到一个点 其所有的子树中最大的子树节点数最少 那么这个点就是这棵树的重心 删去重心后 生成的多棵树尽可能平衡.
2.以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。
树的重心性质
1.树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
2.把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上
3.把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离
树的重心例题
1.sgu 134 Centroid
#include <bits/stdc++.h>
#define INFP 0x3f3f3f3f
#define M (1 << 15)
using namespace std;
int n;
vector <int> ans;
vector <int> vt[M];
int son[M], vis[M], value;
void I(){
ans.clear();
value = INFP;
for(int i=1; i<=n; i++){
vis[i] = 0;
son[i] = 0;
vt[i].clear();
}
}
void N(int u){
vis[u] = 1;
int l = vt[u].size(), tmp = 0;
for(int i=0; i<l; i++){
int v = vt[u][i];
if(vis[v]) continue;
N(v);
son[u] += son[v] + 1;
tmp = max(tmp, son[v] + 1);
}
tmp = max(tmp, n - son[u] - 1);
if(tmp < value){
value = tmp;
ans.clear();
ans.push_back(u);
}
else if(tmp == value)
ans.push_back(u);
}
int main(){
//freopen("in.txt", "r", stdin);
scanf("%d", &n);
I();
for(int i=0; i<n-1; i++){
int u, v;
scanf("%d%d", &u, &v);
vt[u].push_back(v);
vt[v].push_back(u);
}
N(1);
cout << value << " " << ans.size() << endl;
sort(ans.begin(), ans.end());
for(int i=0; i<ans.size(); i++)
cout << ans[i] << " ";
puts("");
return 0;
}
2.poj 1655
#include <algorithm>
#include <iostream>
#include <vector>
#include <stdio.h>
#define INFP 0x3f3f3f3f
#define M (1 << 15)
using namespace std;
int n;
vector <int> vt[M];
int son[M], vis[M], value, id;
void I(){
value = INFP;
for(int i=1; i<=n; i++){
vis[i] = 0;
son[i] = 0;
vt[i].clear();
}
}
void N(int u){
vis[u] = 1;
int l = vt[u].size(), tmp = 0;
for(int i=0; i<l; i++){
int v = vt[u][i];
if(vis[v]) continue;
N(v);
son[u] += son[v] + 1;
tmp = max(tmp, son[v] + 1);
}
tmp = max(tmp, n - son[u] - 1);
if(tmp < value || tmp == value && u < id){
id = u;
value = tmp;
}
}
int main(){
//freopen("in.txt", "r", stdin);
int cas;
scanf("%d", &cas);
while(cas--){
scanf("%d", &n);
I();
for(int i=0; i<n-1; i++){
int u, v;
scanf("%d%d", &u, &v);
vt[u].push_back(v);
vt[v].push_back(u);
}
N(1);
printf("%d %d\n", id, value);
}
return 0;
}
#include <bits/stdc++.h>
#define INFP 0x3f3f3f3f
#define M (1 << 15)
using namespace std;
int n;
vector <int> ans;
vector <int> vt[M];
int son[M], vis[M], value;
void I(){
ans.clear();
value = INFP;
for(int i=1; i<=n; i++){
vis[i] = 0;
son[i] = 0;
vt[i].clear();
}
}
void N(int u){
vis[u] = 1;
int l = vt[u].size(), tmp = 0;
for(int i=0; i<l; i++){
int v = vt[u][i];
if(vis[v]) continue;
N(v);
son[u] += son[v] + 1;
tmp = max(tmp, son[v] + 1);
}
tmp = max(tmp, n - son[u] - 1);
if(tmp < value){
value = tmp;
ans.clear();
ans.push_back(u);
}
else if(tmp == value)
ans.push_back(u);
}
int main(){
//freopen("in.txt", "r", stdin);
scanf("%d", &n);
I();
for(int i=0; i<n-1; i++){
int u, v;
scanf("%d%d", &u, &v);
vt[u].push_back(v);
vt[v].push_back(u);
}
N(1);
cout << value << " " << ans.size() << endl;
sort(ans.begin(), ans.end());
for(int i=0; i<ans.size(); i++)
cout << ans[i] << " ";
puts("");
return 0;
}
#include <algorithm>
#include <iostream>
#include <vector>
#include <stdio.h>
#define INFP 0x3f3f3f3f
#define M (1 << 15)
using namespace std;
int n;
vector <int> vt[M];
int son[M], vis[M], value, id;
void I(){
value = INFP;
for(int i=1; i<=n; i++){
vis[i] = 0;
son[i] = 0;
vt[i].clear();
}
}
void N(int u){
vis[u] = 1;
int l = vt[u].size(), tmp = 0;
for(int i=0; i<l; i++){
int v = vt[u][i];
if(vis[v]) continue;
N(v);
son[u] += son[v] + 1;
tmp = max(tmp, son[v] + 1);
}
tmp = max(tmp, n - son[u] - 1);
if(tmp < value || tmp == value && u < id){
id = u;
value = tmp;
}
}
int main(){
//freopen("in.txt", "r", stdin);
int cas;
scanf("%d", &cas);
while(cas--){
scanf("%d", &n);
I();
for(int i=0; i<n-1; i++){
int u, v;
scanf("%d%d", &u, &v);
vt[u].push_back(v);
vt[v].push_back(u);
}
N(1);
printf("%d %d\n", id, value);
}
return 0;
}