因為是在樹上,所以一定不會走反向邊
每次我們要在樹上找一個到根路徑上點權和最大的點,把答案加上這個和,然後把到根路徑上所有點的點權設為0
因為每個點的點權只會變為0一次,所以我們可以暴力做這個過程
複雜度O((n+k)log n)
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<algorithm>#include<iomanip>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<bitset>using namespace std;#define MAXN 200010#define MAXM 1010#define ll long long#define INF 1000000000#define MOD 1000000007#define eps 1e-8struct vec{ll to;ll fro;};struct data{ll v;ll I;data(){}data(ll _v,ll _I){v=_v;I=_I;}friend bool operator <(data x,data y){return x.v>y.v;}};vec mp[MAXN];ll tai[MAXN],cnt;ll siz[MAXN],dfn[MAXN],ndf[MAXN],tim;data v[MAXN<<2];ll ch[MAXN<<2];ll vis[MAXN];ll a[MAXN];ll ans;ll n,k;ll fa[MAXN];ll s[MAXN];inline void be(ll x,ll y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}void dfs(ll x){ll i,y;siz[x]=1;dfn[x]=++tim;ndf[tim]=x;s[x]=s[fa[x]]+a[x];for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;dfs(y);siz[x]+=siz[y];}}inline void toch(ll x,ll y){v[x].v+=y;ch[x]+=y;}inline void ud(ll x){v[x]=min(v[x<<1],v[x<<1|1]);}inline void pd(ll x){if(ch[x]){toch(x<<1,ch[x]);toch(x<<1|1,ch[x]);ch[x]=0;}}void build(ll x,ll y,ll z){if(y==z){v[x]=data(s[ndf[y]],ndf[y]);return ;}ll mid=y+z>>1;build(x<<1,y,mid);build(x<<1|1,mid+1,z);ud(x);}void change(ll x,ll y,ll z,ll l,ll r,ll cv){if(y==l&&z==r){toch(x,cv);return ;}pd(x);ll mid=y+z>>1;if(r<=mid){change(x<<1,y,mid,l,r,cv);}else if(l>mid){change(x<<1|1,mid+1,z,l,r,cv);}else{change(x<<1,y,mid,l,mid,cv);change(x<<1|1,mid+1,z,mid+1,r,cv);}ud(x);}int main(){ll i,x,y;scanf("%lld%lld",&n,&k);for(i=1;i<=n;i++){scanf("%lld",&a[i]);}for(i=1;i<n;i++){scanf("%lld%lld",&x,&y);fa[y]=x;be(x,y);}dfs(1);build(1,1,n);vis[0]=1;while(k--){x=v[1].I;ans+=v[1].v;while(!vis[x]){vis[x]=1;change(1,1,n,dfn[x],dfn[x]+siz[x]-1,-a[x]);x=fa[x];}}printf("%lld\n",ans);return 0;}/**/