树形DP就是在树状结构基础上的DP
树形DP的关键和实现方法是dfs(深度优先搜索),先找到树根,然后用dfs进行递归到叶子节点,自下而上的更新上层的 f 数组
小白不是很懂为什么树形DP没建树也能做?(这篇题解里面只是有一个树的概念)
树上背包:
#include<iostream>
#include<vector>
using namespace std;
vector<int>v[1314];
int m, n, f[1314][1314],c[1314];//第i门课程,修了j门课程,所得学分(背包问题)
void dfs(int u)
{
for (int i = 0; i < v[u].size(); i++)//循环遍历每一个子节点
{
int x = v[u][i];
dfs(x);
for (int i = m; i >= 0; i--)//枚举总的分配的空间
{
for (int j = 0; j <= i; j++)//枚举子节点花费的空间
f[u][i] = max(f[u][i], f[x][j] + f[u][i - j]);//子节点花费了j的空间,父节点就花费i-j的空间
}
}
for (int i = m; i >= 1; i--)
f[u][i] = f[u][i - 1] + c[u];//把当前u(父节点)加入
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
int a;
cin >> a >> c[i];
v[a]. push_back(i);//把子节点加入到父节点中
}
m++;//*****注意*****因为我们认为构造了一个0作为根节点,所以总的点数应该加一
dfs(0);
cout << f[0][m];
return 0;
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
这道题的重点就是把原来的 森林通过加入一个0节点之后变为了一个以0为根节点的树
然后在这颗树上进行树上背包
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。