题目大致含义就是如果要选子节点的话就要选父节点
那么我们很容易想到了,需要用子节点的值更新父节点的值,所以我们考虑用dfs直接深搜到子节点,然后层层递归更新父亲节点
但是如何更新呢?
这就需要决策了,这需要什么决策?决策给子节点多少容量
这就有点类似于分组背包
分组背包的决策是枚举我们要选择哪个物品
那么我们可以这样理解,在子树更新完毕之后每一个容量值都对应子树的一个权值
那么我们只需要枚举给予子树多少容量就可
需要注意的是子树的的容量和根节点的容量的总和是m
所以子树的背包容量是不能超过当前枚举的总体积j减去其父节点的体积v[u]的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2010;
int e[N],ne[N],h[N],idx;
int n,m,root;
int v[N],w[N],f[N][N];
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs(int u)
{
for(int i=v[u];i<=m;i++) f[u][i] = w[u];
//先初始化,然后开始搜子节点
for(int i=h[u];~i;i=ne[i])
{
int son = e[i];
dfs(son);
for(int j=m;j>=v[u];j--) ///一般都是先循环体积,然后循环决策,啥决策?就是枚举当前的子树用多少容量
for(int k=0;k<=j-v[u];k++)
f[u][j] = max(f[u][j],f[u][j-k]+f[son][k]);
//用子树来更新根节点的值,妙啊
}
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
{
int fa;
cin>>v[i]>>w[i]>>fa;
if(fa==-1) root = i;
else add(fa,i);
}
dfs(root);
cout<<f[root][m];
return 0;
}
要加油啊啊!!!