思路:
先像树链剖分的第一次dfs一样求子树关系,再树形dp
#include<cstdio> #include<iostream> #include<string> #include<queue> #include<cstring> using namespace std; const int maxn = 110; void qread(int &x){ x = 0; register int ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9') x = 10 * x + ch - 48, ch = getchar(); } int n, q; int head[maxn]; int go[maxn << 1]; int val[maxn << 1]; int nxt[maxn << 1]; int f[maxn], l[maxn], r[maxn], deep[maxn], size[maxn], wor[maxn]; int dp[maxn][maxn]; void dfs(int x){ size[x] = 1; for(register int i = head[x]; i; i =nxt[i]){ if(!deep[go[i]]){ f[go[i]] = x; deep[go[i]] = deep[x] + 1; wor[go[i]] = val[i]; if(!l[x]) l[x] = go[i]; else r[x] = go[i]; dfs(go[i]); size[x] += size[go[i]]; } } } void init(){ qread(n); qread(q); for(int i=1; i<n; ++i){ int x, y, z; qread(x), qread(y), qread(z); go[i] = y; val[i] = z; nxt[i] = head[x]; head[x] = i; go[i + n] = x; val[i + n] = z; nxt[n + i] = head[y]; head[y] = n + i; } deep[1] = 1; dfs(1); } int DP(int i, int j){ if(j == 0) return 0; if(!l[i] && !r[i]) return wor[i]; if(dp[i][j] > 0) return dp[i][j]; for(int k=0; k<=j-1; ++k) dp[i][j] = max(dp[i][j], DP(l[i], k) + DP(r[i], j - k - 1) + wor[i]); return dp[i][j]; } int main(void){ init(); printf("%d\n", DP(1, q + 1)); }