poj1155(树形dp)

来源:互联网 发布:阿里云按量付费转包月 编辑:程序博客网 时间:2024/06/13 21:46

这题真心做不来,大牛博客:http://blog.csdn.net/libin56842/article/details/9908199

定义状态:dp[i][j]  根节点i有j个用户对应的最大价值。结果只要重大到小枚举,找打第一个>=0的用户个数。

#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>using namespace std;#define oo 0x3f3f3f3ftypedef long long lld;#define maxn 3003int dp[maxn][maxn];int dp_temp[maxn];int num[maxn], val[maxn];struct EDGE{int v, w, next;}E[maxn];int head[maxn], tol;void inst(){memset(dp, -0x3f, sizeof dp);memset(num, 0, sizeof num);memset(head, -1, sizeof head);tol = 0;}void add_edge(int u, int v, int w){E[tol].v = v;E[tol].w = w;E[tol].next = head[u];head[u] = tol++;}void tree_dp(int fa){for (int i = head[fa]; i != -1; i = E[i].next){int son = E[i].v;tree_dp(son);for (int j = 0; j <= num[fa]; j++)dp_temp[j] = dp[fa][j];for (int j = 0; j <= num[fa]; j++)for (int k = 1; k <= num[son]; k++)dp[fa][j + k] = max(dp[fa][j + k], dp_temp[j] + dp[son][k] - E[i].w);num[fa] += num[son];}}int main(){int n, m, u, v, w, cnt;while (scanf("%d %d", &n, &m) != EOF){inst();for (int i = 1; i <= n - m; i++){scanf("%d", &cnt);while (cnt--){scanf("%d %d", &v, &w);add_edge(i, v, w);}}for (int i = n - m + 1; i <= n; i++){scanf("%d", &dp[i][1]);num[i] = 1;}//没有节点的树价值肯定为0for (int i = 0; i <= n; i++)dp[i][0] = 0;tree_dp(1);int ans = 0;for (int i = m; i >= 0;i--)if (dp[1][i] >= 0){ans = i;break;}printf("%d\n", ans);}return 0;}


0 0