http://poj.org/problem?id=3107
题意:
删掉某点后子树节点最多的最小
思路:
其实就是求树的重心
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
const int maxn=5e4+10;
const int inf=0x7fffffff;
struct Edge
{
int to,next;
}edge[maxn*2];
int head[maxn],tot;
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int n;
int ms[maxn];
int zs[maxn];
int root[maxn];
void init()
{
memset(head,-1,sizeof(head));
tot=0;
}
int num;
void dfs(int x,int pre)
{
zs[x]=1,ms[x]=0;
for(int i=head[x];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)continue;
dfs(v,x);
zs[x]+=zs[v];
ms[x]=max(ms[x],zs[v]);
}
}
int mi;
void dfss(int x,int pre)
{
if(zs[1]-zs[x]>ms[x])ms[x]=zs[1]-zs[x];
if(ms[x]<mi)
{
mi=ms[x];
num=0;
root[++num]=x;
}
else if(ms[x]==mi)
{
root[++num]=x;
}
for(int i=head[x];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)continue;
dfss(v,x);
}
}
int main()
{
while(~scanf("%d",&n))
{
init();
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(1,-1);
num=0;
mi=inf;
dfss(1,-1);
sort(root+1,root+num+1);
for(int i=1;i<=num;i++){
if(i>1)printf(" ");
printf("%d",root[i]);
}
printf("\n");
}
return 0;
}