有 N 个农民, 他们住在 N 个不同的村子里. 这 N 个村子形成一棵树. 每个农民初始时获得 X 的钱. 每一次操作, 一个农民可以从它自己的钱中, 取出任意数量的钱, 交给某个相邻村子的农民. 对于每个农民给定一个值 v_i, 求 (1) 最少需要多少次操作, 使得每个农民最终拿到的钱 >= 给定的值v_i.
傻子都知道是树形dp,但是得变通一下
f[i][j]表示i的子树中用了j次操作,i在使得每个农民最终拿到的钱 >= 给定的值v的条件下能给父亲多少钱
树形背包做:f'[i][j+k]=f[i][k]+f[v][j]
搞定
#include<bits/stdc++.h> using namespace std; int n; long long x,f[2001][2001],val[2001],g[2001]; int sz[2001]; vector<int> e[2001]; void merge(int x,int y){ int i,j; for(i=0;i<sz[x];i++)g[i]=f[x][i]; for(i=0;i<sz[x]+sz[y];i++)f[x][i]=-2147483648ll; for(i=0;i<sz[x];i++){ for(j=0;j<sz[y];j++){ if(f[y][j]>=0)f[x][i+j]=max(f[x][i+j],g[i]); f[x][i+j+1]=max(f[x][i+j+1],g[i]+f[y][j]); } }sz[x]+=sz[y]; for(i=1;i<sz[x];i++)f[x][i]=max(f[x][i-1],f[x][i]); } void dfs(int u,int fa){ int i,j; f[u][0]=f[u][1]=x-val[u],sz[u]=1; int v,k; for(i=0;i<e[u].size();i++){ v=e[u][i]; if(v==fa)continue; dfs(v,u),merge(u,v); } } int main(){ int i; cin>>n>>x; for(i=1;i<=n;i++)scanf("%lld",&val[i]); for(i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); e[a].push_back(b),e[b].push_back(a); } dfs(1,0); for(i=0;i<n;i++)if(f[1][i]>=0)break; cout<<i<<endl; return 0; }