题目大意:奶牛构成一个树形结构,0为根(不能选择0)
每头牛选择可以得到C[i]的收益,选择其和其父亲可以增加一对父子关系
在满足收益大于X的前提下,求最多的父子关系数
题解:树上背包
很容易想到f[i][j][0/1]表示以i为根的子树,存在j对父子关系,不选/选i的最大收益,最后一维方便转移
初始值f[x][0][1]=c[x],f[x][0][0]=0,为了不选0,令f[0][0][1]=−INF
决策有三种
我的收获:树形dp套路……
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int M=505;
#define INF 0x3f3f3f3f
int n,fa,tar,ans=-1;
int t,head[M],c[M];
int f[M][M][2];
struct edge{int to,nex;}e[M<<1];
void add(int u,int v){e[t].to=v,e[t].nex=head[u],head[u]=t++;}
void dfs(int x)
{
f[x][0][1]=c[x],f[x][0][0]=0;
if(!x) f[x][0][1]=-INF;
for(int i=head[x];i!=-1;i=e[i].nex){
int v=e[i].to;dfs(v);
for(int j=n;j>=0;j--)//显然要倒序……
for(int k=0;k<=j;k++){
if(k) f[x][j][1]=max(f[x][j][1],f[x][j-k][1]+f[v][k-1][1]);//x和v都选,增加一对父子关系
f[x][j][1]=max(f[x][j][1],f[x][j-k][1]+f[v][k][0]);//选x不选v
f[x][j][0]=max(f[x][j][0],f[x][j-k][0]+max(f[v][k][0],f[v][k][1]));//不选x,v选不选都可以
}
}
}
void work()
{
for(int i=0;i<=n;i++) if(f[0][i][0]>=tar) ans=i;
printf("%d\n",ans);
}
void init()
{
memset(head,-1,sizeof(head));
memset(f,0xc0,sizeof(f));
scanf("%d%d",&n,&tar);
for(int i=1;i<=n;i++){
scanf("%d%d",&c[i],&fa);
add(fa,i);
}dfs(0);
}
int main()
{
init();
work();
return 0;
}