http://poj.org/problem?id=2378
题意:
给一颗n个结点的树,节点编号为1~n,把删除一个节点之后,
剩下的分支中节点数量最多的数量不大于总数量一半的编号全部按顺序输出
思路:
跟求树的重心一样的方法,先从下往上更新,在从上往下跟新即可。
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
const int maxn=1e4+10;
struct node
{
int to,next;
}edge[maxn*2];
int n;
int head[maxn],tot;
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void init()
{
memset(head,-1,sizeof(head));
tot=0;
}
int zs[maxn],ms[maxn];
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]);
}
}
void dfss(int x,int pre)
{
if(zs[1]-zs[x]>ms[x])ms[x]=zs[1]-zs[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);
dfss(1,-1);
for(int i=1;i<=n;i++)
{
if(ms[i]<=n/2)
{
printf("%d\n",i);
}
}
}
return 0;
}