題目地址: 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;}/*71 22 52 33 43 66 7*/