Description
Input
Output
Sample Input
6 9
1 1 1
1 1 100
8 1 1
1 3 6
2 3 1000
4 1 4
Sample Output
105
【样例解释】
其中一种最优解为:小 C?用 8 点能量摘下第 1,2,4,6 朵花,并放在药材中熬煮,由于第 4 朵花所钦慕的 3 号花不在药材中,所以第 4 朵花渐渐枯萎消失。最后剩下 3 朵花:1,2,6,药材所获得的最大贡献为 1+100+4=105。
Data Constraint
分析:其实复杂度主要浪费在合并两个儿子的答案。所以我们可以把一个儿子的答案直接给下一个儿子,就可以了。也就是设f[i][j]表示从根选到i,以及i点左边的子树,容量为j的答案,转移显然。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=5007;
using namespace std;
int f[maxn][10003];
int n,p,x,cnt;
int val[maxn],w[maxn],ls[maxn],size[maxn],dfn[maxn];
struct node{
int y,next,w;
}g[maxn*4];
void dfs(int x)
{
dfn[++cnt]=x;
size[x]=1;
for (int i=ls[x];i>0;i=g[i].next)
{
dfs(g[i].y);
size[x]+=size[g[i].y];
}
}
int main()
{
freopen("medicine.in","r",stdin);
freopen("medicine.out","w",stdout);
scanf("%d%d",&n,&p);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&w[i],&x,&val[i]);
if (i!=1)
{
g[i].y=i;
g[i].next=ls[x];
ls[x]=i;
}
}
dfs(1);
for (int i=n;i>0;i--)
{
int k=dfn[i];
for (int j=0;j<=p;j++) f[i][j]=max(f[i+size[k]][j],0);
for (int j=w[k];j<=p;j++) f[i][j]=max(f[i][j],f[i+1][j-w[k]]+val[k]);
}
int ans=0;
for (int i=0;i<=p;i++) ans=max(ans,f[1][i]);
printf("%d",ans);
}