HDU 1011 (树背包)

坑点是特判。

#include <bits/stdc++.h>
using namespace std;
#define maxn 111
#define maxm 222

struct node {
    int from, to, next;
}edge[maxm];
int bug[maxn], brain[maxn];
int n, m, head[maxn];
int ans;
int dp[maxn][maxn];
int degree[maxn];

void add_edge (int from, int to, int i) {
    node &e = edge[i];
    e.from = from, e.to = to, e.next = head[from], head[from] = i;
}

void dfs (int u, int fa) {
    for (int i = bug[u]; i <= m; i++) {
        dp[u][i] = brain[u];
    }
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        if (v == fa)
            continue;
        dfs (v, u);
        for (int j = m; j >= bug[u]; j--) {
            for (int k = 1; j+k <= m; k++) {
                dp[u][j+k] = max (dp[u][j+k], dp[u][j]+dp[v][k]);
            }
        }
    }
}

int main () {
    //freopen ("in", "r", stdin);
    while (cin >> n >> m) {
        if (n == -1 && m == -1)
            break;
        for (int i = 1; i <= n; i++) {
            cin >> bug[i] >> brain[i];
            bug[i] = ceil (bug[i]*1.0/20);
        }
        memset (head, -1, sizeof head);
        int u, v;
        int cnt = 0;
        memset (degree, 0, sizeof degree);
        for (int i = 1; i < n; i++) {
            cin >> u >> v;
            add_edge (u, v, cnt++);
            add_edge (v, u, cnt++);
            degree[u]++;
            degree[v]++;
        }
        if (m == 0) {
            printf ("0\n");
            continue;
        }
        for (int i = 2; i <= n; i++)
            if (degree[i] == 1)
                bug[i] = max (1, bug[i]); //如果是叶子节点 至少需要一个士兵
        memset (dp, 0, sizeof dp);
        dfs (1, 0);
        printf ("%d\n", dp[1][m]);
    }
    return 0;
}


你可能感兴趣的:(HDU 1011 (树背包))