刚开始贪心每次最小的叶子去掉,wa了几次发现思路是错了。正解是简单的树形dp。
#pragma warning(disable:4996)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
vector<int>g[105];
int num[105][105], cnt[105];//cnt[u]表示结点u的子树中有几条树枝
int dp[105][105];//dp[u][i]表示结点u的子树中保留i条树枝可获得的最大值
int n, q;
bool vis[105];
void getcnt(int u){
vis[u] = true;
cnt[u] = 0;
for (int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if (!vis[v]){
cnt[u]++;
getcnt(v);
cnt[u] += cnt[v];
}
}
}
void dfs(int u){
vis[u] = true;
int first = 0, second = 0;
for (int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if (!vis[v]){
if (first)second = v;
else first = v;
dfs(v);
}
}
if (second){//2 child
for (int i = 1; i < n; i++){
if (i>cnt[u]){
dp[u][i] = -1;
continue;
}
dp[u][i] = 0;
if (cnt[first] >= i - 1){
dp[u][i] = max(dp[u][i], num[u][first] + dp[first][i - 1]);
}
if (cnt[second] >= i - 1){
dp[u][i] = max(dp[u][i], num[u][second] + dp[second][i - 1]);
}
//dp[u][i] = max(dp[first][i - 1] + num[u][first], dp[second][i - 1] + num[u][second]);
int tmp = num[u][first] + num[u][second];
for (int j = 0; j <= i - 2; j++){
if (cnt[first] >= j&&cnt[second] >= i - 2 - j)
dp[u][i] = max(dp[u][i], tmp + dp[first][j] + dp[second][i - 2 - j]);
}
}
}
else if (first){//1 child
for (int i = 1; i < n; i++){
if (i>cnt[u]){
dp[u][i] = -1;
continue;
}
if (cnt[first] >= i - 1){
dp[u][i] = num[u][first] + dp[first][i - 1];
}
//dp[u][i] = num[u][first] + dp[first][i - 1];
}
}
else{//0 child
for (int i = 1; i < n; i++)dp[u][i] = -1;
}
}
int main(){
//freopen("in.txt", "r", stdin);
scanf("%d %d", &n, &q);
for (int i = 1; i < n; i++){
int u, v, c; scanf("%d %d %d", &u, &v, &c);
g[u].push_back(v);
g[v].push_back(u);
num[u][v] = num[v][u] = c;
}
memset(vis, false, sizeof vis);
getcnt(1);
memset(vis, false, sizeof vis);
dfs(1);
printf("%d\n", dp[1][q]);
return 0;
}