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<<'\n'; }