简单树形dp
状态转移方程: ans[i] = max(dp[j], n-dp[i]) j为i的所有子节点,dp[i]为以i为根的子树结点个数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define min(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int maxn=20005;
int n, cnt, dp[maxn], pre[maxn], ans, nod; // dp[]-->number of son_node
struct node{
int v, next;
}edge[maxn*2];
void add_edge(int s, int t){
edge[cnt].v=t;
edge[cnt].next=pre[s];
pre[s]=cnt++;
}
int dfs(int s, int f){
int i;
dp[s]=1;
for(i=pre[s]; i!=-1; i=edge[i].next){
if(edge[i].v==f)continue;
dp[s]+=dfs(edge[i].v, s);
}
return dp[s];
}
void init(){
scanf("%d", &n);
int i, s, t;
cnt=0;ans=n;
memset(pre, -1, sizeof(pre));
memset(dp, 0, sizeof(dp));
for(i=1; i<n; i++){
scanf("%d%d", &s, &t);
add_edge(s, t);
add_edge(t, s);
}
dfs(1, 1);
}
void dfs2(int s, int f){
int i, t=n-dp[s];
for(i=pre[s]; i!=-1; i=edge[i].next){
if(edge[i].v==f)continue;
t=max(dp[edge[i].v], t);
dfs2(edge[i].v, s);
}
if(t<ans||(t==ans&&s<nod)){ans=t;nod=s;}
}
void solve(){
dfs2(1, 1);
printf("%d %d\n", nod, ans);
}
int main(){
//freopen("1.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--){
init();
solve();
}
return 0;
}