新子树的重心一定在重儿子到根的路径上
暴力向上跳即可
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> using namespace std; typedef long long ll; const int maxn = 200010; const int INF = 1000000007; int n; int h[maxn],cnt=0; struct E{ int next,to; }e[maxn*2]; void add(int u,int v){ e[++cnt].to=v; e[cnt].next=h[u]; h[u]=cnt; } int sz[maxn],a[maxn],fa[maxn],son[maxn],b[maxn]; int fin(int x,int u){ int ma=INF,tt,an=x; // tt = max(sz[son[x]],sz[u]-sz[x]); while(x!=fa[u] && max(sz[son[x]],sz[u]-sz[x])<=ma){ if(max(sz[son[x]],sz[u]-sz[x])==ma){ b[u] = x; }else if(max(sz[son[x]],sz[u]-sz[x])<ma){ ma=max(sz[son[x]],sz[u]-sz[x]); an=x; } x = fa[x]; } return an; } int dfs1(int u,int par){ int nu = 0; fa[u] = par;sz[u]=1; for(int i=h[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v==par) continue; int sv = dfs1(v,u); if(sv>nu){ nu = sv; son[u] = v; } sz[u] += sv; } return sz[u]; } void dfs2(int u,int par){ a[u] = u; for(int i=h[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v==par) continue; dfs2(v,u); if(v==son[u]){ int x = a[son[u]]; a[u] = fin(x,u); } } } ll read(){ int s=0,f=1; char ch = getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch = getchar(); } while(ch>='0' && ch<='9'){ s = s*10 + ch - '0'; ch = getchar(); } return s*f; } int main(){ memset(h,-1,sizeof(h)); n = read(); int u,v; for(int i=1;i<n;i++){ u = read(), v = read(); add(u,v); add(v,u); } dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;i++){ if(b[i]!=0 && b[i]<a[i]) swap(a[i],b[i]); printf("%d",a[i]); if(b[i]) printf(" %d",b[i]); printf(" "); } return 0; }