~~~~~ P10641 BZOJ3252 攻略 ~~~~~ 总题单链接
思路
~~~~~ 发现可以贪心,每次选择一条权值最大的路径,记录贡献后将路径上的点权设为 0 0 0。
~~~~~ 又发现其实选择最大路径的过程就是找一条长链使得链上的权值之和最大,所以用长链剖分。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,Q,cnt;
vector<ll>eg[200005],v;
ll a[200005],vis[200005];
ll len[200005],son[200005];
void dfs_build(ll p){
for(ll v:eg[p]){
dfs_build(v);
if(len[son[p]]<len[v])son[p]=v;
}
len[p]=len[son[p]]+a[p];
}
signed main(){
ios::sync_with_stdio(false);
cin>>n>>Q;
for(ll i=1;i<=n;i++)cin>>a[i];
for(ll i=1;i<n;i++){
ll x,y;cin>>x>>y;
eg[x].push_back(y);
}
dfs_build(1);
for(ll i=1;i<=n;i++)vis[son[i]]=1;
for(ll i=1;i<=n;i++)if(!vis[i])v.push_back(len[i]);
sort(v.begin(),v.end());
ll sum=0;
for(ll i=v.size()-1;i>=v.size()-Q;i--)
sum+=v[i];
cout<<sum;
return 0;
}