1. 程式人生 > >|洛谷|動態規劃|P2014 選課

|洛谷|動態規劃|P2014 選課

http://www.luogu.org/problem/show?pid=2014

(注意題目資料範圍有誤,建議開陣列到2000)

經典樹形依賴揹包問題。

因為可能出現森林,所有要建立一個虛結點0,將森林中所有樹的根節點作為結點0的兒子

f[i][j]表示以i為根選j個課程

f[u][j] = max(f[u][j], f[u][j-k]+f[v][k]); //v是u的兒子

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ms(i,j) memset(i, j, sizeof(i));
using namespace std;
int n,m;
int t;
int w[2005];
vector<int>G[2005];
int f[2005][2005];
void dfs(int u)
{
	for (int i=1;i<=m;i++) 
	f[u][i] = w[u];//必選u 
	for (int i=0;i<G[u].size();i++)
	{
		int v = G[u][i];
		dfs(v);
		for (int j=t;j>=2;j--)
		{
			for (int k=1;k<j;k++)
			{
				f[u][j] = max(f[u][j], f[u][j-k]+f[v][k]);
			}
		}
	}
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i=1;i<=n;i++)
	{
		int ki;
		scanf("%d%d", &ki, &w[i]);
		G[ki].push_back(i);
	}
	t = m+1;//增加了一個虛結點0,將森林轉為樹,所以t=m+1
	dfs(0);
	printf("%d\n", f[0][m+1]);
	return 0;
}