1.树最多有两个重心
2.如果树有两个重心那么它们两两相邻
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N = 200010;
vector<int> h[N];
int n;
int res = N;
int dfs(int u,int fa) {
int sum = 1;
int mn = 1;
for (auto a : h[u]) {
if (a == fa) continue;
int num = dfs(a, u);
mn = max(mn, num);
sum += num;
}
mn = max(mn, n - sum);
res = min(mn, res);
return sum;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
h[a].push_back(b);
h[b].push_back(a);
}
dfs(1,-1);
cout << res << endl;
return 0;
}
练习题
思路:找到树的重心,一个直接输出
两个的话把一个的叶节点断开,连到另一个上
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
const int N = 200010;
vector<int> h[N];
vector<int> tmp,gg;
int ans = N;
int n,kk;
int dfs(int u, int fa) {
int sum = 1;
int maxn = 1;
for (auto a : h[u]) {
if (a == fa) continue;
int num = dfs(a, u);
maxn = max(maxn, num);
sum += num;
}
maxn = max(maxn, n - sum);
if (maxn < ans) {
tmp.clear();
ans = maxn;
tmp.push_back(u);
}
else if (maxn == ans) {
tmp.push_back(u);
}
return sum;
}
void find(int a, int b,int fa) {
if (kk) return;
if (h[a].size() == 1) {
kk = a;
gg.push_back(a);
gg.push_back(h[a][0]);
return;
}
for (auto g : h[a]) {
if (g == b || g == fa) continue;
find(g, b, a);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
gg.clear();
tmp.clear();
ans = N;
cin >> n;
for (int i = 1; i <= n; i++) h[i].clear();
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
h[a].push_back(b);
h[b].push_back(a);
}
dfs(1, -1);
if (tmp.size() == 1) {
int g = -1;
for (auto a : h[tmp[0]]) {
g = a;
break;
}
cout << tmp[0] << " " << g << endl << tmp[0] << " " << g<<endl;
}
else {
kk = 0;
find(tmp[0], tmp[1],-1);
cout << gg[0] << " " << gg[1] << endl;
cout << tmp[1] << " " << gg[0] << endl;
}
//cout << ans << endl;
}
return 0;
}