思路
如果一棵树有两个重心,那么从一个重心的一边切割一个点到另外一个重心即可。
如果一棵树只有一个重心,那么随意断掉一个点再恢复即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
struct edge {
int to, next;
} e[N * 2];
int head[N], idx = 1;
void add(int u, int v) {
idx++, e[idx].to = v, e[idx].next = head[u], head[u] = idx;
}
int sz[N];
int n;
int mx[N];
vector<int> ans;
void getroot(int u, int fa) {
sz[u] = 1;
mx[u] = 0;
for (int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if (to == fa) continue;
getroot(to, u);
mx[u] = max(mx[u], sz[to]);
sz[u] += sz[to];
}
mx[u] = max(mx[u], n - sz[u]);
if (mx[u] * 2 <= n) {
ans.push_back(u);
}
}
int del_edge, last;
void dfs(int u, int fa) {
// cout << u << ' ' << fa << endl;
last = u;
for (int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if (to == fa) continue;
del_edge = i;
dfs(to, u);
}
}
void solve() {
memset(head, 0, sizeof(int) * (n + 10));
memset(mx, 0, sizeof(int) * (n + 10));
idx = 1;
ans.clear();
cin >> n;
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
add(x, y), add(y, x);
}
getroot(1, 0);
if (ans.size() == 1) {
cout << e[3].to << ' ' << e[2].to << '\n';
cout << e[3].to << ' ' << e[2].to << '\n';
}
else {
del_edge = 0;
dfs(ans[0], ans[1]);
cout << e[del_edge].to << ' ' << e[del_edge ^ 1].to << '\n';
cout << e[del_edge].to << ' ' << ans[1] << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) solve();
return 0;
}
标签:sz,head,Cut,idx,int,Centroids,getroot,Link,mx
From: https://www.cnblogs.com/Yuan-Jiawei/p/18348441