可怜与超市
//T4 可怜与超市
//long long!!!!我看到10的九次方了,我直接龙龙
//不对啊,b也小于10亿啊,int就够了
//我聪明的大脑瞬间看出,树形DP
//题干的意思是不是1就是根?应该是,但我觉得不稳
//f[u][0/1] 以u为根的子树,u买或者不买的能购买的最多商品 最优解(之所以这么定义因为跑不了10亿乘5000)
//0是不买 带点背包思想,选课那种,这个注意
//f[u][0]+=(f[v][0])
//f[u][1]+=(f[v][1],f[v][0]) 最后轮一遍最优
//就这?????
//现在就是我不知道它是否会是一个森林,或者就是以1为根
//这样吧,我赌一把,1根,没有森林
//不对,这样还是不好做,我这个值没法算啊
//要不还是一开始的思路,去算钱,然后再比
//关键, ....5000*5000能开嘛 ,是五千万,应该可以,
//那行,改了改了,全改了
//f[i][j][0/1] 以i为根的子树,买j件的最小价值 还是选课那个背包思想,与i的儿子进行轮k
//那么0 1 就表示用不用优惠劵 0是不用
//考完了我总结一下,就是:加权选课用上皇宫的状态思想 嘶,你这么一总结,这可真是一道好题,高低是把树形整透了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mx=5000+10;
int n,len;
ll b;
int head[mx];
ll c[mx],d[mx];
ll f[mx][mx][2];
int size[mx];//这跟选课还有些不同,这我得开一个记录它的儿子个数
//额怎么说,其实怎么着都能写,不过我觉得这种写法还清晰一些
struct Node{
int from;
int to;
int next;
}a[mx];
void Insert(int u,int v){
a[++len].from=u;
a[len].to=v;
a[len].next=head[u];
head[u]=len;
}
void dfs(int u){
f[u][0][0]=0;
f[u][1][0]=c[u];
f[u][1][1]=c[u]-d[u];
// printf("1k f[%d][1][1]=%lld c[%d]=%lld d[%d]=%lld\n",u,f[u][1][1],u,c[u],u,d[u]);
size[u]=1;
for(int i=head[u];i!=0;i=a[i].next){
int v=a[i].to;
dfs(v);
//这个题的k的顺序一直是无所谓的,当前处理的子树拿出来的,从几开始轮都行
//j的顺序必须是这样,如果是j-k,就是一开始就把总数算出了,其实就相当于一个01背包
//j是总容积,k每次填进去,它每次都是有一些从j-k更新的,如果从0到j,就是可能这个点前面
//已经用过了,我再后面又用了一次,点也是每次只能用一次 ,与DP无后效性相符
//如果是j+k,j+k每次从j更新,还是说它从小于它的更新,就得倒序,无后效性
//如果下标为负,它会根据你的数组在内存的位置 更新你数组里的其它的值,
//如果在前面就run 后面就会w或者多跑了很多次导致t,这个注意
//关于当j-k 因为我们的答案j是从左右上来的
// 这么说,当j=总时,k没有选择,只能全部奉上,其他都是无意义的;如果你进行j-k
// 当k不是size[v],就需要左边付出更多,笑死,它根本没有,从这里理解它也是无意义的
// 然后有个细节就是k要大于j-kk,但你还是要跟0取个max,因为j也会变小
// k在右边为了防止j-k<0 也要处理
//这个题是透的不能再透了
int kk=size[u];
size[u]+=size[v];
for(int j=size[u];j>=0;--j){
// j-k<=kk j-kk<=k
for(int k=max(0,j-kk