题意:给你一棵树,每个节点都有一个价值,但每个价值只能加一次,选择k次图上叶子节点到叶子节点,使得这k次经过的价值最大(注意不能重复)。
思路:找一个点当作根节点,长链刨分。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
typedef long long ll;
int head[N],nxt[N<<2],to[N<<2];
ll s[N];
int cnt=0;
void add(int u,int v)
{
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
int son[N];
ll value[N];
priority_queue<ll>Q;
//求价值
void dfs1(int x)
{
for(int i=head[x];i;i=nxt[i])
{
if(to[i]!=x)
dfs1(to[i]);
if(value[to[i] ]>value[son[x] ])
son[x]=to[i];
}
value[x]=value[son[x] ]+s[x];
}
//最大路径
void dfs2(int x,int top)
{
if(x==top)Q.push(value[x]);
if(son[x])dfs2(son[x],top);
for(int i=head[x];i;i=nxt[i])
{
if(to[i]!=x && to[i]!=son[x])
dfs2(to[i],to[i]);
}
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%lld",&s[i]);
for(int i=0;i<n-1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
dfs1(1);
dfs2(1,1);
ll ans=0;
while(k&&!Q.empty())ans+=Q.top(),Q.pop(),k--;
printf("%lld",ans);
}