#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3000 + 10;
int n, m; //节点数 叶子节点数
int a[maxn];
int head[maxn<<1], edge[maxn<<1], ver[maxn<<1], nex[maxn<<1], tot;
inline void add_edge(int x, int y, int z){
ver[++tot] = y; edge[tot] = z;
nex[tot] = head[x]; head[x] = tot;
}
int f[maxn][maxn];
int dfs(int x)
{
if(x > n - m)
{
f[x][1] = a[x];
return 1;
}
int sum = 0, t; //sum表示该节点最多选多少个用户,也就是背包的容量
for(int i = head[x]; i; i = nex[i])
{
int y = ver[i], z = edge[i];
t = dfs(y); sum += t;
for(int j = sum; j >= 0; j--)
for(int k = 0; k <= t; k++) //t是子树的用户端 枚举选1个,2个....
if(j - k >= 0)
f[x][j] = max(f[x][j], f[x][j-k]+f[y][k]-z);
} return sum;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1, k, y, z; i <= n-m; i++)
{
scanf("%d", &k);
for(int j = 1; j <= k; j++)
{
scanf("%d%d", &y, &z);
add_edge(i, y, z);
}
}
for(int i = n - m + 1; i <= n; i++)
scanf("%d", &a[i]);
memset(f, 0xcf, sizeof f);
//什么都不选的价值就是0
for(int i = 1; i <= n; i++)
f[i][0] = 0;
dfs(1);
for(int i = m; i >= 1; i--)
if(f[1][i] >= 0)
{
cout << i << endl;
break;
}
return 0;
}
原文:https://www.cnblogs.com/zxytxdy/p/12075267.html