## [CF1223E] Paint the Tree - 树形dp
### Description
在树上选取一些边,保证没有点度超过 k,求最大边权和
### Solution
用 $f[i][0/1]$ 表示处理了 i 的子树,i 的度小于等于 k 或 k-1 时的最大答案
注意在跳过边权 <0 的边
``` cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n, k;
cin >> n >> k;
vector<vector<pair<int, int>>> g(n + 2);
vector<vector<int>> f(n + 2, vector<int>(2));
for (int i = 1; i < n; i++)
{
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
}
function<void(int, int)> dfs = [&](int p, int from) -> void {
vector<int> vec;
int sum = 0;
for (auto [q, w] : g[p])
if (q != from)
{
dfs(q, p);
vec.push_back(f[q][1] + w - f[q][0]);
sum += f[q][0];
}
sort(vec.begin(), vec.end());
reverse(vec.begin(), vec.end());
int first_k = 0, first_km1 = 0;
for (int i = 0; i < k && i < vec.size() && vec[i] > 0; i++)
first_k += vec[i];
for (int i = 0; i + 1 < k && i < vec.size() && vec[i] > 0; i++)
first_km1 += vec[i];
f[p][0] = sum + first_k;
f[p][1] = sum + first_km1;
};
dfs(1, 0);
int ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, max(f[i][0], f[i][1]));
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
solve();
}