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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章