思路:
设fi,j,0/1表示i子树,给j个单位时间,最后走不走回来的最大价值
c o d e code code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, m, tot;
int a[505], head[505], f[505][505][2];
struct node {
int to, next;
} b[10010];
void add(register int x, register int y) {
b[++tot] = (node){ y, head[x] };
head[x] = tot;
}
void dp(register int x, register int fa) {
for(int i = head[x]; i; i = b[i].next) {
int y = b[i].to;
if(y == fa) continue;
dp(y, x);
for(int j = m; j >= 1; j --)
for(int k = 0; k <= j; k ++) {
if(j - k >= 2)
f[x][j][0] = max(f[x][j][0], f[x][j - k - 2][0] + f[y][k][0]),
f[x][j][1] = max(f[x][j][1], f[x][j - k - 2][1] + f[y][k][0]);
if(j - k >= 1)
f[x][j][1] = max(f[x][j][1], f[x][j - k - 1][0] + f[y][k][1]);
}
}
for(int i = m; i >= 1; i --)
f[x][i][0] = max(f[x][i][0], f[x][i - 1][0] + a[x]),
f[x][i][1] = max(f[x][i][1], f[x][i - 1][1] + a[x]);
}
int main() {
scanf("%d%d", &n, &m);
for (register int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (register int i = 1; i < n; i++) {
register int x, y;
scanf("%d%d", &x, &y);
add(x, y), add(y, x);
}
dp(1, 0);
printf("%d", f[1][m][1]);
return 0;
}