Kill the tree 计蒜客42552 (重心

新子树的重心一定在重儿子到根的路径上

暴力向上跳即可

#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;
}
原文地址:https://www.cnblogs.com/tuchen/p/13764324.html