题解主要在注释里
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int f[N][N],v[N],w[N],n,m;
int e[N],h[N],ne[N],idx;
/*
有依赖的背包问题
转化成树状结构
当我们想知道节点u的最优解,那么我们就需要得到节点u的子节点们的最优解
因此我们可以转化成dfs来解决
f[u][j]表示以u为子树的物品,在体积不超过容量j时所获得的最大价值
我们可以把u的每个子节点看做一个组,每组物品按单位体积拆分,作为决策循环
那么就有0,1,2...j-v[u]种不同的决策(为什么呢?因为节点的子节点仍然有子节点
我们不能单纯得以最后一个来特别判断,我们不确定子节点的子节点的体积是什么
那么我们就直接把单位体积作为决策)
*/
/*
状态转移方程的推导:
f[u][j]表示以u为子树的物品,在体积不超过容量j时所获得的最大价值
因为我们是回溯进行分组背包
那么我们的转移方程为
设t为节点u的一个子节点
f[u][j]=max(f[u][j],f[u][j-k]+f[t][k]);
其中j为我们遍历的体积,从大到小就行
k是我们的决策,从0~j-v[u],原因在于我们会为节点u留一个体积
*/
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 t=e[i];
dfs(t);
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[t][k]);
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
int root;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
{
int p;
cin>>v[i]>>w[i]>>p;
if (p==-1)
root=i;
else
add(p,i);
}
dfs(root);
cout<<f[root][m];
return 0;
}