dsu on tree —— BAPC2019 A

据说这个是长链剖分。。

自底向上树形dp,维护住子树里最深的那个叶子即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define N 200005
ll n,k,a[N],num[N];
vector<int>G[N];

int d[N],leave[N],son[N];
void getdeep(int u,int pre){//获取每个叶子的深度 
    int flag=0;
    for(auto v:G[u]){
        if(v==pre)continue; 
        flag=1;d[v]=d[u]+1;
        getdeep(v,u);
    }
    if(!flag)leave[u]=1;
}

void getnum(int u,int pre){
    if(leave[u]){son[u]=u;return;} 
    for(auto v:G[u]){
        if(v==pre)continue;
        getnum(v,u);
        if(d[son[v]]>d[son[u]])
            son[u]=son[v];
        num[son[v]]++;
    }
}
int cmp(ll a,ll b){return a>b;}
int main(){
    cin>>n>>k;
    for(int i=1;i<=k;i++)cin>>a[i];
    sort(a+1,a+1+k,cmp);
    for(int i=2;i<=n;i++){
        int u=i,v;cin>>v;v++;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    d[1]=0;
    getdeep(1,1);
    getnum(1,1);
    sort(num+1,num+1+n,cmp);
    ll ans=0;
    for(int i=1;i<=k;i++)
        ans+=num[i]*a[i];
    cout<<ans<<'
';
}
原文地址:https://www.cnblogs.com/zsben991126/p/12541767.html