在树上跑dp;一般都是dfs和bfs,有点像记忆化,向子树要答案,然后可以向上返回,在递归的过程中去dp,,与前面的dp类似,不同的是递归过程中跑dp;

 1 int dfs(int x){
 2     if (x > n - m){
 3         f[x][1] = v[x];
 4         return 1;
 5     }
 6     int ret = 0;
 7     for (int k = first[x]; k; k = e[k].next){
 8         int to = e[k].to;
 9         int t = dfs(to);
10         ret += t;
11         for (int j = ret; j > 0; --j){
12             for (int i = 1; i <=min(j,t); ++i){
13                 f[x][j] = max(f[x][j], f[x][j-i] + f[to][i] - e[k].w);
14             }
15         }
16     }
17     return ret;
18 }

//这是洛谷p1273与这类似

树上背包

无依赖关系

int n,m;
vector<int>son[N];
int f[1010][1010];
int val[1010];
void dfs(int x) {
    for (int a : son[x]) {
        dfs(a);
        for (int j = m; j >= 0; --j) {
            for (int k = 0; k <= j; ++k) {
                f[x][j] = max(f[x][j], f[x][j - k]+f[a][k]+val[x]);
            }
        }
    }
}

有依赖关系

选子必须选父

int n,m;
vector<int>son[N];
int f[1010][1010];
int val[1010];
void dfs(int x) {
    f[x][1] = val[x];
    for (int j = 2; j <= m; ++j) {
        f[x][j] = f[x][j - 1];
    }
    for (int a : son[x]) {
        dfs(a);
        for (int j = m; j >= 0; --j) {
            for (int k = 0; k <= j; ++k) {
                f[x][j] = max(f[x][j], f[x][j - k]+f[a][k]);
            }
        }
    }
}