Benelux Algorithm Programming Contest 2019 A. Appeal to the Audience

思路:显然,每个人至少上场一次。
一个 显然 的性质,挂在同一个节点上的所有叶子,只能有一个叶子能额外上场。
我们需要让能力大的人上场次数最多。
那么我们在dfs的时候 需要让出场次数最多的叶子接着出场。
然后从大到小分配给按能力从大到小排序的球员。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int n,k,a[N],b[N],c[N];
vector<int>v[N],g;
void dfs(int now){
  int mx=-1;
  for(auto k:v[now]){
    dfs(k);
    mx=max(mx,c[k]);
  }
  c[now]=mx+1;
  sort(v[now].begin(),v[now].end(),[](int x,int y){return c[x]>c[y];});
  for(int i=1;i<v[now].size();i++){
    if(c[v[now][i]])g.pb(c[v[now][i]]);
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin>>n>>k;LL ans=0;
  for(int i=1;i<=k;i++)cin>>a[i],ans+=a[i];
  for(int i=2;i<=n;i++){
    int x;cin>>x;
    v[++x].pb(i);
  }
  dfs(1);
  sort(a+1,a+1+n,[](int x,int y){return x>y;});
  int l=0;g.pb(c[1]-1);
  sort(g.begin(),g.end(),greater<int>());
  for(int i=0;i<g.size();i++){
    ans+=1ll*g[i]*a[++l];
  }
  cout<<ans<<'\n';
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40655981/article/details/105028960