本来是为了写树分治才写这个题的没想到竟然浪费了好长时间
狂wa不止原来前向星的数组要开两倍。。。第一次用前向星真是光荣牺牲了。。。
dp很简单
先DFS一次,求出以每个节点为根的子树的节点个数s[i].
设f[i]表示去掉i后,余下的各个子树结点个数的最大值.
f[i]=max(n-s[i],max{s[j]}). (j为i的儿子).
然后输出f[i]最小的点就可以了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAX 50009
#define rep(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
int n,head[MAX],size[MAX],next[MAX],tot=0;
int to[MAX],done[MAX],f[MAX];
void add(int from,int To)
{
tot++;
to[tot]=To;
next[tot]=head[from];
head[from]=tot;
}
void dfs(int x)
{
done[x]=1;
size[x]=1;
for(int i=head[x];i!=-1;i=next[i])
if(!done[to[i]])
dfs(to[i]),size[x]+=size[to[i]];
return;
}
int main()
{
int time;
scanf("%d",&time);
while(time--)
{
tot=0;
memset(to,0,sizeof(to));
memset(head,-1,sizeof(head));
memset(next,-1,sizeof(next));
scanf("%d",&n);
rep(i,1,n-1)
{
int a1,a2;
scanf("%d%d",&a1,&a2);
add(a1,a2);
add(a2,a1);
}
memset(done,0,sizeof(done));
memset(f,0,sizeof(f));
memset(size,0,sizeof(size));
dfs(1);
//rep(i,1,n)
// printf("--%d %d\n",i,size[i]);
rep(i,1,n)
f[i]=n-size[i];
rep(i,1,n)
{
int Max=-0x7fffffff,p;
for(int j=head[i];j!=-1;j=next[j])
if(size[to[j]]>Max&&size[i]>size[to[j]])
Max=size[to[j]];
f[i]=max(f[i],Max);
}
//rep(i,1,n)
// printf("==%d %d\n",i,f[i]);
int Max=0x7fffffff,p;
rep(i,1,n)
if(f[i]<Max)
Max=f[i],p=i;
printf("%d %d\n",p,Max);
}
return 0;
}