http://poj.org/problem?id=3107
题意:给出n个点,n-1条边,去掉一个点(x)后形成的子树最多点 最小的点(x)
以前貌似做过,现在重新用树形dfs缕缕思路
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define Max(a,b)a>b?a:b
#define Min(a,b)a<b?a:b
#define MAX 50005
using namespace std;
int head[MAX],mark[MAX],vs[MAX],sumVal[MAX],maxSub[MAX];
int n,s_edge,cnt,MIN;
struct Edge
{
int to,nxt;
}edge[MAX*2];
void addedge(int u,int v)
{
s_edge++;
edge[s_edge].to=v;
edge[s_edge].nxt=head[u];
head[u]=s_edge;
s_edge++;
edge[s_edge].to=u;
edge[s_edge].nxt=head[v];
head[v]=s_edge;
}
void dfs(int x)
{
vs[x]=1;
sumVal[x]=1;
maxSub[x]=0;
for(int e=head[x];e;e=edge[e].nxt)
{
int v=edge[e].to;
if(!vs[v])
{
dfs(v);
sumVal[x]+=sumVal[v];
maxSub[x]=Max(maxSub[x],sumVal[v]);
}
}
int k;
k=Max(n-sumVal[x],maxSub[x]);//这里 还出过错,最大中的最小、、、
if(k==MIN)
mark[cnt++]=x;
else if(k<MIN)
{
MIN=k;
cnt=0;
mark[cnt++]=x;
}
return ;
}
int main()
{
int i,a,b;
scanf("%d",&n);
memset(head,0,sizeof(head));
s_edge=0;
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
memset(vs,0,sizeof(vs));
cnt=0;
MIN=50010;
dfs(1);
sort(mark,mark+cnt);
for(i=0;i<cnt;i++)
{
if(i==0) printf("%d",mark[i]);
else printf(" %d",mark[i]);
}
printf("\n");
return 0;
}