题意:一棵树,定义每个节点的balance值:去掉这点节点后的森林里所有树的最大节点数。求出最小的balance值和其所对应的节点编号。
对于删除的每一个点,计算下它的每颗子树的节点数与剩余的子树的节点数,做一下比较。
dp[x][0] 以x节点为根的子树的最大节点数
dp[x][1] 包含x祖先的子树的节点数
注意边界的处理
#include <vector>
#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 2e4+7;
int n,dp[maxn][2],c[maxn];
vector<int>q[maxn];
void dfs(int x,int fa)
{
c[x]=1;dp[x][1]=dp[x][0]=0;
int i,f=0;
for(i=0;i<q[x].size();i++)
{
int u=q[x][i];
if(u==fa) continue;
f++;
dfs(u,x);c[x]+=c[u];
dp[x][0]=max(dp[x][0],c[u]);
}
if(!f) dp[x][0]=dp[x][1]=n-1;
else dp[x][1]=n-c[x];
}
int main()
{
int i,t,x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++) q[i].clear();
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
q[x].push_back(y);
q[y].push_back(x);
}
dfs(1,0);
int ans1=0,ans2=INF;
for(i=1;i<=n;i++)
{
int temp=max(dp[i][0],dp[i][1]);
if(temp<ans2)
ans2=temp,ans1=i;
}
printf("%d %d\n",ans1,ans2);
}
return 0;
}