持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。
题目
中文大意
给我们n个结点形成的树每个节点都有一个价值每经过这一结点我们都会获得一次我们有k次机会从根节点走到叶结点但是一个结点的所以子结点经历过的次数最多与最小与最小的差值不能超过1问我们k次机会能获得的最大价值是多少
解法
如果这个结点现在有次机会走它有个子节点所以每个子节点最少能分到次机会剩下的%次机会都会分给能产生最大价值子节点也就是说明这些子节点会比其它子节点多一个机会所以对于一些根节点的所以子节点我们只需要将他们如果加一次机会产生的价值排序即可
int dfs(int x,int cnt) {
res += s[x] * cnt;
if(!v[x].size()) return s[x];
priority_queue<int> q;
for(auto u : v[x]) q.push(dfs(u,cnt/v[x].size()));
int t = cnt % v[x].size();
while(t--) {
res += q.top(),q.pop();
}
return q.top() + s[x];
}
我们的cnt是我们至少能获得的机会如果我们再获得一次机会时我们产生的价值是他的子节点的第大的值其他的同理
int p[N],s[N];
int res = 0;
vector<int> v[N];
int dfs(int x,int cnt) {
res += s[x] * cnt;
if(!v[x].size()) return s[x];
priority_queue<int> q;
for(auto u : v[x]) q.push(dfs(u,cnt/v[x].size()));
int t = cnt % v[x].size();
while(t--) {
res += q.top(),q.pop();
}
return q.top() + s[x];
}
void solve()
{
int n,k; cin >> n >> k;
rep(i,n) v[i].clear();
for(int i = 2; i <= n; i++) cin >> p[i],v[p[i]].pb(i);
rep(i,n) cin >> s[i];
res = 0;
dfs(1,k) ;
cout << res << endl;
}