The key to freedom (key. PAS/C/CPP) is stored in N rooms, which are connected by n-1 corridor. However, each room has a special protection magic. Under its role, I cannot pass through this room or get the key. Although I can destroy the magic in the room by consuming energy, my energy is limited. So, if I stand in Room 1 first (the protection magic of Room 1 is still valid, that is, if I do not consume energy, I cannot pass Room 1, can't get the key in the room). If my energy is P, how many keys can I get at most? The first line of the input data contains two non-negative integers. The first is N, and the second is P. Next n rows, by 1 ~ The Order N describes each room. Line I + 1 contains two non-negative integers cost and keys, respectively, which are the energy required to cancel the magic in room I and the number of keys in the room. In the next n-1 line, two non-negative integers x and y in each row indicate that room X is connected to room y. An integer in a row of output data indicates that the maximum value of the key is obtained. Sample input: Key. in 5 5 1 2 1 1 1 1 2 3 3 3 4 1 1 3 2 2 4 2 5 output: Key. out 7 data range for 20% of test data, n <= 20 for 30% of test data, n <= 30 for all test data, P, n <= 100, cost <= maxint, keys <= maxint
A signature-based DP.
First, use dual-cross and then DP.
Using keys: F [I] [J] indicates the maximum number of keys that can be obtained using J energy.
Moving equations: f [I] [J] = max (F [son [I] [k] + F [bro [I] [J-K-C [I] + V [I], f [bro [I] [J]).
When loading data, the data is first converted to an undirected sequence, and then the root sequence is not set to a sequence. Otherwise, the data is very heavy; the energy consumed by a certain vertex can be 0, so J = 0 cannot be regarded as a condition.
Accode:
#include <cstdio>#include <cstring>#include <cstdlib>#include <bitset>using std::max;const char fi[] = "key.in";const char fo[] = "key.out";const int maxN = 110;const int maxM = 110;const int MAX = 0x3fffff00;const int MIN = -MAX;struct Edge {int dest; Edge *next; };Edge *edge[maxN];int f[maxN][maxM];int bro[maxN];int son[maxN];int c[maxN];int v[maxN];int n, m; void init_file() { freopen(fi, "r", stdin); freopen(fo, "w", stdout); } void insert(int u, int v) { Edge *p = new Edge; p -> dest = v; p -> next = edge[u]; edge[u] = p; } void readdata() { scanf("%d%d", &n, &m); for (int i = 1; i < n + 1; ++i) scanf("%d%d", c + i, v + i); for (int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); insert(u, v); insert(v, u); } } int DP(int i, int j) { if (i == 0) return 0; if (f[i][j]) return f[i][j]; if (bro[i]) f[i][j] = max(f[i][j], DP(bro[i], j)); if (j >= c[i]) for (int k = 0; k + c[i] < j + 1; ++k) { f[i][j] = max(f[i][j], DP(son[i], k) + DP(bro[i], j - k - c[i]) + v[i]); } return f[i][j]; } void Build(int u, int Last) { for (Edge *p = edge[u]; p; p = p -> next) { int v = p -> dest; if (v != Last) { Build(v, u); bro[v] = son[u]; son[u] = v; } } } void work() { Build(1, 0); DP(1, m); printf("%d", f[1][m]); } int main(){ init_file(); readdata(); work(); exit(0);}