by luogu
大致题意:给出一棵树,求在一定费用下能够达到最多叶子数。
emmm...一道树上背包(多重
从树形dp思路来考虑状态的设置:
dp[i][j] -->以i节点为根,选j个用户
我们不难发现我们需要预先知道儿子状态,所以我们dfs
套个多重背包的模版,然后dfs注意下状态转移
#include<bits/stdc++.h> using namespace std; const int N=3e3+7; int n,m; //i为根节点节点j为费用,dp[y][j]=max(dp[y][k]dp[x][j-k] ) //dp[x][j] dp[y][k] ---> dp[x][j+k] int dp[N][N],val[N]; int head[N],nxt[10000010],to[10000010],edge[10000010]; int _; void add(int x,int y,int z) { _++; to[_]=y; edge[_]=z; nxt[_]=head[x]; head[x]=_; return ; } int dfs(int x) { if(x>n-m) { dp[x][1]=val[x]; return 1; } int re=0; for(int i=head[x];i;i=nxt[i]) { int y=to[i],z=edge[i]; int v=dfs(y); re+=v; for(int j=re;j>=1;j--) { for(int k=1;k<=v;k++) if(j-k>=0) dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k]-z); } } return re; } int main() { ios::sync_with_stdio(false); cin>>n>>m; memset(dp,-0x3f, sizeof(dp)); for(int i=1;i<=n-m;i++) { int num; cin>>num; for(int j=1;j<=num;j++) { int q,w; cin>>q>>w; add(i,q,w); } } for(int i=n-m+1;i<=n;i++) cin>>val[i]; for(int i=1;i<=n;i++) dp[i][0]=0; dfs(1); for(int i=m;i>0;i--) { if(dp[1][i]>=0) { cout<<i; return 0; } } return 0; }