给出一个森林,每棵树均为一组物品,首先推出每棵树可以组成的物品种类。
然后是基本的分组背包模板。
即 最外层枚举组数,次外层枚举背包容量,内层枚举物品体积。
对于每棵树有 ans[root][i+j] = ans[root][ i ] + ans[son][ j ]。
题水数据也水,不多说了。
#include <iostream> #include <algorithm> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <stack> #include <map> #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-8) #define LL long long #define ULL unsigned long long int #define _LL __int64 #define _INF 0x3f3f3f3f #define Mod 1000000007 #define LM(a,b) (((ULL)(a))<<(b)) #define RM(a,b) (((ULL)(a))>>(b)) using namespace std; const int MAXN = 210; struct N { int u,v,w,next; } edge[MAXN*2]; int head[MAXN]; int Top; void Link(int u,int v,int w = -1) { edge[Top].u = u; edge[Top].v = v; edge[Top].w = w; edge[Top].next = head[u]; head[u] = Top++; } void Init_head_Top(int n) { memset(head,-1,sizeof(int)*(n+2)); Top = 0; } int dp[MAXN]; int ans[MAXN][MAXN]; int root[MAXN]; int Top_Root; int price[MAXN]; void dfs(int s,int m) { ans[s][1] = price[s]; for(int p = head[s] ; p != -1; p = edge[p].next) { dfs(edge[p].v,m); for(int i = m;i >= 0; --i) { for(int j = m-i;j >= 1; --j) { if(ans[s][i] != -1 && ans[s][i+j] < ans[s][i] + ans[edge[p].v][j]) ans[s][i+j] = ans[s][i] + ans[edge[p].v][j]; } } } } int main() { int n,m; int i,j,k,v; while(scanf("%d %d",&n,&m) && (n||m)) { Init_head_Top(n); Top_Root = 0; memset(dp,-1,sizeof(dp)); memset(ans,-1,sizeof(ans)); for(i = 1; i <= n; ++i) { scanf("%d %d",&v,&price[i]); if(v) Link(v,i); else root[Top_Root++] = i; } for(i = 0; i < Top_Root; ++i) { dfs(root[i],m); } dp[0] = 0; for(j = 0; j < Top_Root; ++j) { for(i = m;i >= 0; --i) { if(dp[i] != -1) { for(k = m-i;k >= 1; --k) { if(ans[root[j]][k] != -1 && dp[i] != -1 && dp[i+k] < dp[i] + ans[root[j]][k]) dp[i+k] = dp[i] + ans[root[j]][k]; } } } } // for(i = 1; i <= m; ++i) // { // // printf("cost = %2d w = %2d\n",i,dp[i]); // } // // for(i = 1; i <= n; ++i) // { // for(j = 1; j <= m; ++j) // { // //printf("%2d ",ans[i][j]); // // } // // puts(""); // } int Max = dp[1]; for(i = 1; i <= m ; ++i) Max = max(Max,dp[i]); printf("%d\n",Max); } return 0; }