You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

57 lines
2.0 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 310;
int n, m;
int w[N];
int f[N][N];
//创建邻接表
int h[N], e[N], ne[N], idx;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
//分组背包过程
void dfs(int u) {
for (int i = h[u]; i != -1; i = ne[i]) {//物品组
dfs(e[i]);
for (int j = m - 1; j >= 0; j--) //体积
for (int k = 0; k <= j; k++) //决策
f[u][j] = max(f[u][j], f[u][j - k] + f[e[i]][k]);
}
//把老大加上去,同样由于滚动数组对于自己本行的依赖,所以采用了倒序
//给老大预留了一个位置1,所以i>=1
for (int i = m; i >= 1; i--) f[u][i] = f[u][i - 1] + w[u];
//要注意0这个边界当当前节点的选课数量为0时是没有意义的所以需要初始化为0但是其本身就是0
//所以这里直接不循环即可,类比一下10_2.cpp
//f[u][0]=0;
}
int main() {
/**
DP+01-->
m+1(0~m)
kk,:f(s1,k)
O(n*m^2)
0f[0,m+1]
0m+1
*/
cin >> n >> m;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i++) {
int p;
cin >> p >> w[i];
//添加虚拟根的技巧
add(p, i);//若不存在先修课则该项为0:这为我们创建虚拟根0号结点创造了条件
}
//所有方案都需要添加虚拟根结点0就相当于选了m+1门课
m++;
dfs(0);
cout << f[0][m] << endl;//由于m已经++所以这里就是f[0][m]了
return 0;
}