A Knapsack Problem - hackerrank
阿新 • • 發佈:2018-11-09
題意
\(n(1 \leq n \leq 1000)\)個結點的樹,每個結點有重量\(w\)和價值\(v\)兩個屬性,現在給你一個大小為\(m(1 \leq m \leq 1000)\)的揹包,求能得到的最大價值。注:選取的結點一定是一個連通塊。
題解
待補
程式碼
using namespace std; const int N = 2005; int n, m; int s[N], v[N], subtree[N], label[N], dp[N][N]; bool deleted[N]; vector<int> adj[N]; void DFS(int u, int par = -1) { subtree[u] = 1; for (auto v : adj[u]) if ((!deleted[v]) && (v != par)) { DFS(v, u); subtree[u] += subtree[v]; } label[n] = u; n--; } int central(int u, int par = -1) { int w = 0; for (auto v : adj[u]) if ((!deleted[v]) && (v != par)) { if (subtree[v] > subtree[w]) w = v; } if (w == 0) return (u); if (subtree[w] + subtree[w] <= n) return (u); return (central(w, u)); } int calc(int n) { Rep(i, 0, n) Rep(j, 0, m) dp[i][j] = -INF32; dp[1][s[label[1]]] = v[label[1]]; Rep(i, 2, n) { int u = label[i]; Rep(j, 0, m) { if (j >= s[u]) dp[i][j] = max(dp[i][j], dp[i - 1][j - s[u]] + v[u]); dp[i + subtree[u] - 1][j] = max(dp[i + subtree[u] - 1][j], dp[i - 1][j]); } } int res = 0; Rep(i, 0, m) res = max(res, dp[n][i]); return res; } int solve(int tree, int tree_size) { n = tree_size; DFS(tree); n = tree_size; int r = central(tree); n = tree_size; DFS(r); int res = calc(tree_size); deleted[r] = true; for (auto v : adj[r]) if (!deleted[v]) res = max(res, solve(v, subtree[v])); return res; } int main() { BEGIN() { sc(n), sc(m); Rep(i, 0, n) deleted[i] = false; Rep(i, 0, n) adj[i].clear(); Rep(i, 1, n) sc(s[i]); Rep(i, 1, n) sc(v[i]); rep(i, 1, n) { int u, v; sc(u), sc(v); adj[u].pb(v); adj[v].pb(u); } int result = solve(1, n); pr(result); } return 0; }