首先看到题目的第一反应,就是边上的权值不好处理,感觉非常麻烦,仔细一看,可以把边pushdown,反正一个结点只有一个父亲,那么就把边的权值放到对应孩子结点上,那么就大功告成了。
用二维数组求解问题,确定状态,用dp[root][y]表示结点root保留y个点(下放完事了以后是点,点会比边多一个,最后求的时候加1就好了)

dp[root][y]由本身和左子树 右子树够成,左子树+右子树+本身应该是等于y个点
那么通过枚举左子树、右子树的所有可能,就可以完成
代码实现先跑一遍找到对应的孩子,再进行记忆化搜索dp

#include <bits/stdc++.h>
using namespace std;
const int N=105;
int dp[N][N];
int G[N][N];
int val[N];
vector <int> vec[N];
int n,q;
struct node
{
    int l,r;
    node(){l=r=0;}
}tree[N];
void pushdown(int root,int pre)
{
    for(int i=0;i<vec[root].size();i++)
    {
        int to=vec[root][i];
        if(to==pre) continue;
        if(tree[root].l==0) tree[root].l=to;
        else if(tree[root].r==0) tree[root].r=to;
        pushdown(to,root);
        val[to]=G[root][to];
    }
}
int dfs(int root,int y)
{
    int left=0,right=0;
    if(dp[root][y]) return dp[root][y];
    if(root==0) return 0;
    int ans=0;
    dp[root][1]=val[root];
    for(int k=0;k<y;k++){
        left=dfs(tree[root].l,k);
        right=dfs(tree[root].r,y-1-k);
        ans=max(ans,left+right+dp[root][1]);
    }
    dp[root][y]=ans;
    return dp[root][y];
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<n;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        G[u][v]=G[v][u]=w;
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    pushdown(1,0);
    printf("%d\n",dfs(1,q+1));
}