题说的很明白,就是求树的重心。
我们首先dfs一遍维护每一个点的子树大小,然后再dfs一遍,对于一个点u,选择子树中size[v]最小的那个和n - size[u]比较,取最大作为删除u后的答案Max[u]。
然后再O(n)遍历一遍取min(Max[i]).
写代码的时候两次dfs可以合并。
然后这题竟然卡vector,不得不用链前存图……简直有毒。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 5e4 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n; 38 struct Node 39 { 40 int nxt, to; 41 }e[maxn << 1]; 42 int head[maxn], ecnt = 0; 43 void add(int x, int y) 44 { 45 e[++ecnt].to = y; 46 e[ecnt].nxt = head[x]; 47 head[x] = ecnt; 48 } 49 50 bool vis[maxn]; 51 int siz[maxn], Max[maxn]; 52 void dfs(int now, int fa) 53 { 54 siz[now] = 1; Max[now] = -1; 55 for(int i = head[now]; i; i = e[i].nxt) 56 { 57 if(e[i].to == fa) continue; 58 dfs(e[i].to, now); 59 siz[now] += siz[e[i].to]; 60 Max[now] = max(Max[now], siz[e[i].to]); 61 } 62 Max[now] = max(Max[now], n - siz[now]); 63 } 64 65 int main() 66 { 67 n = read(); 68 Mem(vis, 0); Mem(head, 0); ecnt = 0; 69 for(int i = 1; i < n; ++i) 70 { 71 int x = read(), y = read(); 72 add(x, y); add(y, x); 73 } 74 dfs(1, 0); 75 int Min = INF; 76 for(int i = 1; i <= n; ++i) Min = min(Min, Max[i]); 77 for(int i = 1; i <= n; ++i) if(Max[i] == Min) write(i), space; 78 enter; 79 return 0; 80 }