給定一棵樹,找到重心:移除該點後,剩餘各連通塊(子樹)中最大節點數最小。輸出重心編號及該最大子樹大小。
sz[u]:以 u 為根的子樹大小。u,其移除後產生的塊大小為:sz[v],以及「父方向」塊 n - sz[u]。max( max_child_sz, n - sz[u] )。sz 並更新全局最小平衡值對應的節點。#include <bits/stdc++.h>
using namespace std;
const int MAXN = 20010, INF = 0x3f3f3f3f;
struct Edge { int v, nxt; } e[MAXN<<1];
int h[MAXN], ec, n, ans, minBal;
int sz[MAXN];
void addEdge(int u, int v) {
e[ec] = {v, h[u]}; h[u] = ec++;
}
void init() { fill(h, h+n+1, -1); ec = 0; minBal = INF; }
void dfs(int u, int fa) {
sz[u] = 1; int mx = 0;
for (int i = h[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
if (v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
mx = max(mx, sz[v]);
}
mx = max(mx, n - sz[u]); // 父方向塊
if (mx < minBal) { minBal = mx; ans = u; }
}
int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
init();
for (int i = 1, u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
addEdge(u, v); addEdge(v, u);
}
dfs(1, 0);
printf("%d %d\n", ans, minBal);
}
return 0;
}
O(n),單次 DFS。O(n)。n - sz[u],易漏。< 保證首個最小)。