poj 1155 TELE 樹形揹包dp
阿新 • • 發佈:2019-02-18
dp[i][we] 代表節點為i 給k個消費者提供訊號的所賺錢術 這時we就是揹包容量,每個子節點的每個dp[son][j] 0 <=j<= num[j]; 就是各個物品了
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define mini -100000000
#define maxn 3005
using namespace std;
int dp[maxn][maxn], n, m, va[maxn], num[maxn];
int last[maxn * 2 ], Next[maxn * 2], edge[maxn * 2], cost[maxn * 2], l;
void add(int a, int b, int va)
{
edge[l] = b;
cost[l] = va;
Next[l] = last[a];
last[a] = l;
l++;
}
void dfs(int pre)
{
for(int i = last[pre]; i != -1; i = Next[i])
{
dfs(edge[i]);
num[pre] += num[edge[i]];
for (int j = num[pre]; j >= 0; j--)
for(int k = min(j ,num[edge[i]]); k >= 0; k--)
dp[pre][j] = max(dp[pre][j], dp[edge[i]][k] + dp[pre][j - k] - cost[i]);
}
}
int main()
{
while(scanf("%d%d", &n, &m)!=EOF)
{
l = 0;
memset(last, -1, sizeof (last));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) dp[i][j] = mini;
for(int i = 1; i<= n - m; i++)
{
num[i] = 0;
int k;
scanf("%d", &k);
while(k--)
{
int a, b, c;
scanf("%d%d", &a, &b);
add(i, a, b);
}
}
for(int i = n - m + 1; i <= n; i++)
{
num[i] = 1;
scanf("%d", &dp[i][1]);
}
dfs(1);
for(int i = m; i >= 0; i--) if(dp[1][i] >= 0) {printf("%d\n", i); break;}
}
return 0;
}