//数据量比较小,没有太多的优化 #include<iostream> #include<cstdio> #include<cstring> #define maxn 205 using namespace std; int n,m,a,b,idx; int head[maxn],val[maxn]; int dp[maxn][maxn];//dp[x][j]以点x为根,容量为j的最大价值 struct node { int to,next; }edg[maxn]; int max(int x,int y) { return x>y?x:y; } void init() { idx=0; memset(dp,sizeof(dp)); memset(head,-1,sizeof(head)); } void addNode(int from,int to)//头插法建立邻接链表 { edg[idx].to=to; edg[idx].next=head[from]; head[from]=idx++; } void dfs(int x) { dp[x][1]=val[x];//只装根节点的价值 for(int i=head[x];i!=-1;i=edg[i].next) { int to=edg[i].to; dfs(to); //将以to为根的数打包 for(int j=m+1;j>=1;j--)//分组背包,每组的物品只能用一次 { for(int k=0;k<j;k++) { dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[to][k]); } } } } int main() { while(scanf("%d%d",&n,&m)) { if(!n&&!m) break; init(); for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); addNode(a,i); val[i]=b; } val[0]=0; dfs(0); printf("%d\n",dp[0][m+1]); } return 0; } =========================================== // //这题还可以使用泛化背包的写法,能优化一些时间 #include<iostream> #include<stdio.h> #include<string.h> #define maxn 205 using namespace std; int n,g,idx,ans; int c[maxn],v[maxn],head[maxn],use[maxn]; int dp[maxn][maxn]; struct node { int to; int next; }edg[maxn]; inline int max(int x,int y) //用inline来省时 { if(x>y) return x; return y; } void init(int n) { memset(dp[0],sizeof(int)*(g+2)); memset(head,sizeof(int)*(n+1)); memset(use,sizeof(int)*(n+1)); idx=0; ans=0; } void addNode(int from,int to) { edg[idx].to=to; edg[idx].next=head[from]; head[from]=idx++; } void dfs(int now,int lim)//表示已选x的情况下,用lim更新子节点 { for(int i=head[now];i!=-1;i=edg[i].next) { int j=edg[i].to; //不是叶子节点 if(use[j]) { if(lim-c[j]>=0) { for(int k=lim-c[j];k>=0;k--) //给子树初值 dp[j][k]=dp[now][k]; dfs(j,lim-c[j]); //让子树打包 for(int k=c[j];k<=lim;k++) //合并 { dp[now][k]=max(dp[now][k],dp[j][k-c[j]]+v[j]);//选或不选子树的某个背包 } } } else { for(int k=lim;k>=c[j];k--) { dp[now][k]=max(dp[now][k-c[j]]+v[j],dp[now][k]);//01背包 } } } } int main() { int i,a; v[0]=0; c[0]=1; while(scanf("%d %d",&g)!=EOF) { if(!g&&!n) break; init(n); for( i=1;i<=n;i++) { int f; scanf("%d %d",&v[i]); //if(i==f) f=0; c[i]=1; use[a]++; addNode(a,i); } dfs(0,g); for( i=0;i<=g+1;i++) ans=max(ans,dp[0][i]); printf("%d\n",ans); } return 0; }