【题意】:给你一棵树,去掉一个结点后,得到的平衡值是指分开的所有子树中结点数的最大值,求去掉哪个点,平衡值最小。
【题解】:dfs一次,把无向树变成有向树。顺便统计以每个结点为根的树的结点数,记为cnt[].
那么点u的平衡值 balance[u] = max(n - cnt[u], max(cnt[v])),其中 v 为 u 的儿子。
最后,ans = { u | balance[u] = min(balance[])};
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 using namespace std;
8 #define pb push_back
9 #define maxn 20050
10 vector<int> vec[maxn];
11 int n;
12 int balance[maxn], cnt[maxn];
13
14 void dfs(int u, int fa) {
15 int size = vec[u].size();
16 cnt[u] = 1;
17 int tmp = 0;
18 for(int i = 0; i < size; i++) {
19 int v = vec[u][i];
20 if(v == fa) continue;
21 dfs(v, u);
22 cnt[u] += cnt[v];
23 tmp = max(cnt[v], tmp);
24 }
25 balance[u] = max(tmp, n - cnt[u]);
26 }
27
28 int main() {
29 int T, u, v;
30 scanf("%d", &T);
31 while(T--) {
32 scanf("%d", &n);
33 for(int i = 0; i < maxn; i++) vec[i].clear();
34 for(int i = 0; i < n - 1; i++) {
35 scanf("%d%d", &u, &v);
36 vec[u].pb(v), vec[v].pb(u);
37 }
38 dfs(1, -1);
39 int ans = 1;
40 for(int i = 1; i <= n; i++) {
41 if(balance[ans] > balance[i]) ans = i;
42 }
43 cout << ans << " " << balance[ans] << endl;
44 }
45 return 0;
46 }