1. 程式人生 > 實用技巧 >有依賴的揹包問題

有依賴的揹包問題

題目傳送門

思路

我們可以把依賴關係用一棵樹來表示,我們選了一個節點就節點的父親都要選。

然後我們可以把有依賴的揹包問題看成是分組揹包問題,每一個結點是看成是分組揹包問題中的一個組,子節點的每一種選擇我們都看作是組內的一種物品,因此我們可以通過分組揹包的思想去寫。

但我們如何去遍歷子節點的每一種選擇,即組內的物品,我們的做法是從葉子結點開始往根節點做,並使用陣列表示的鄰接表來存貯每個結點的父子關係

#include <bits/stdc++.h>
using namespace std;
int n,m,root,head[105],nxt[105],ver[105],cnt,v[105],w[105],f[105][105];

void add_edge(int u,int v) { ver[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt; }

void dfs(int u) {
	for(int i=head[u];i;i=nxt[i]) {
		int son=ver[i];
		dfs(son);
		for(int j=m-v[u];j>=0;j--) {
			for(int k=0;k<=j;k++)
				f[u][j]=max(f[u][j],f[u][j-k]+f[son][k]);
		}
	}
	for(int i=m;i>=v[u];i--) f[u][i]=f[u][i-v[u]]+w[u];
	for(int i=0;i<v[u];i++) f[u][i]=0;
	return ;
}

int main() {
	scanf("%d %d",&n,&m);
	for(int i=1,x;i<=n;i++) {
		scanf("%d %d %d",&v[i],&w[i],&x);
		if(x==-1) root=i;
		else add_edge(x,i);
	}
	dfs(root);
	printf("%d",f[root][m]);
	return 0;
}