题目地址: http://poj.org/problem?id=3107
DFS遍历。
利用树化区间的思想。
能想到这个方法,就很好做了。
枚举每一个节点为断点:
1. 那么其每【一个子节点】=【一颗单独的树】。
2. 而【整棵树】减去【以这个节点为根的树】=【单独一棵树】。
#include<iostream>
#include<cstdio>
#include<cstring>
#define bug puts("here");
using namespace std;
struct Edge{
int gt,nx;
}edge[110000];
int ef[51000],tol;
void add_edge(int a,int b){
edge[tol].gt=b;
edge[tol].nx=ef[a];
ef[a]=tol++;
}
int has[51000];
int lft[51000],rit[51000];
int now;
int father[51000];
void dfs(int x){
int k;
lft[x]=++now;
has[x]=1;
for(k=ef[x];k!=-1;k=edge[k].nx){
if(has[edge[k].gt]) continue;
dfs(edge[k].gt);
father[edge[k].gt]=x;
}
rit[x]=now;
}
int res[51000],cnt;
int getlen(int x){
return rit[x]-lft[x]+1;
}
int main(){
int n,i,a,b,k,mn,tmp;
scanf("%d",&n);
memset(ef,-1,sizeof(ef));
tol=0;
for(i=1;i<n;i++){
scanf("%d%d",&a,&b);
add_edge(a,b);
add_edge(b,a);
}
now=0;
dfs(1);
father[1]=-1;
for(i=1;i<=n;i++){
if(father[i]==-1){
mn=100000;
tmp=0;
}
else{
tmp=getlen(1)-getlen(i);
}
for(k=ef[i];k!=-1;k=edge[k].nx){
if(father[i]==edge[k].gt) continue;
if(tmp<getlen(edge[k].gt))
tmp=getlen(edge[k].gt);
}
if(tmp<mn){
cnt=0;
mn=tmp;
res[cnt++]=i;
}
else if(tmp==mn){
res[cnt++]=i;
}
}
printf("%d",res[0]);
for(i=1;i<cnt;i++)
printf(" %d",res[i]);
puts("");
return 0;
}
/*
7
1 2
2 5
2 3
3 4
3 6
6 7
*/