BZOJ
給定一棵樹,每一個點有點權,選定\(k\)個葉子,知足根到\(k\)個葉子的全部路徑所覆蓋的點權和最大。php
一個僞裝是對的貪心:
每次選擇最大的路徑,而後將路徑上全部點的權值清零。
那麼咱們能夠用長鏈剖分來實現這個貪心。
鏈長改成最大的路徑權值和,這樣子把每條重鏈的權值丟進一個堆裏面取\(k\)次便可。
正確性本身\(YY\)一下,發現是對的ios
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; #define ll long long #define MAX 200200 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } priority_queue<ll> Q; struct Line{int v,next;}e[MAX<<1]; int h[MAX],cnt=1; inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;} int a[MAX],n,K,hson[MAX]; ll ms[MAX],ans; void dfs1(int u) { for(int i=h[u];i;i=e[i].next) { int v=e[i].v;dfs1(v); if(ms[v]>ms[hson[u]])hson[u]=v; } ms[u]+=a[u]+ms[hson[u]]; } void dfs2(int u,int tp) { if(u==tp)Q.push(ms[u]); if(hson[u])dfs2(hson[u],tp); for(int i=h[u];i;i=e[i].next) if(e[i].v!=hson[u])dfs2(e[i].v,e[i].v); } int main() { n=read();K=read(); for(int i=1;i<=n;++i)a[i]=read(); for(int i=1,x,y;i<n;++i)x=read(),y=read(),Add(x,y); dfs1(1);dfs2(1,1); while(K&&!Q.empty())ans+=Q.top(),Q.pop(),--K; printf("%lld\n",ans); return 0; }