【題意】:給你一棵樹,去掉一個結(jié)點后,得到的平衡值是指分開的所有子樹中結(jié)點數(shù)的最大值,求去掉哪個點,平衡值最小。
【題解】:dfs一次,把無向樹變成有向樹。順便統(tǒng)計以每個結(jié)點為根的樹的結(jié)點數(shù),記為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 }