题目链接:https://vjudge.net/problem/HYSBZ-4033
考虑每个边对答案的贡献
dp[i][j]表示以i为根的子树中共选取j个黑色的点,对答案的贡献。
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define pb push_back
#define ll long long
using namespace std;
const int N = 3100;
int n,m;
int tot,head[N];
ll dp[N][N],siz[N];
struct E{
int v;
ll w;
int nxt;
}edge[N*2];
void ae(int u,int v,ll w) {
tot++;
edge[tot] = (E){v,w,head[u]};
head[u] = tot;
}
void dfs(int u,int f) {
dp[u][0] = dp[u][1] = 0;
siz[u] = 1;
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
ll w = edge[i].w;
if(v==f) continue;
dfs(v,u);
int P1 = min(siz[u],1ll*m);
per(j, P1, 0) {
per(k, min(siz[v],1ll*m-j), 0) {
ll num1 = k*(m-k);
ll num2 = (siz[v]-k)*(n-m-siz[v]+k);
dp[u][j+k] = max(dp[u][j+k],dp[u][j]+dp[v][k]+w*(num1+num2));
}
}
siz[u]+=siz[v];
}
}
int main() {
// freopen("a.txt","r",stdin);
scanf("%d%d",&n,&m);
rep(i, 1, n) head[i] = -1;
rep(i, 1, n-1) {
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
ae(u,v,w);
ae(v,u,w);
}
dfs(1,0);
printf("%lld",dp[1][m]);
return 0;
}