洛谷P2015 二叉蘋果樹
阿新 • • 發佈:2021-08-05
題意:
數有\(N\)個節點,根編號為\(1\),一根樹枝連線兩個編號,樹枝上有一定數量的蘋果,給定需要保留的邊數,求最多能留住多少蘋果。
思路:
樹形\(DP\) + 有依賴的揹包問題
看成有依賴的揹包問題:f[u][j]就表示以\(u\)為根節點的子樹,選\(j\)條邊的最大價值。
那麼轉移方程:\(f[u][j] = max(f[u][j], f[u][j - 1 - k] + f[son][k] + w[i])\)
為什麼有一個\(f[u][j - 1 - k]\)而不是\(f[u][j - k]\)呢,因為在\(u\)與\(son\)之間本來就有一條邊,所以需要減去。
#include <bits/stdc++.h> using namespace std; const int N = 110, M = N * 2; int h[N], e[M], ne[M], w[M], idx; int n, m; int f[N][N]; void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } void dfs(int u, int father) { for (int i = h[u]; ~i; i = ne[i]) { int son = e[i]; if (son == father) continue; dfs(son, u); for (int j = m; j >= 0; j--) { for (int k = 0; k <= j - 1; k++) { f[u][j] = max(f[u][j], f[u][j - 1 - k] + f[son][k] + w[i]); } } } } int main() { cin >> n >> m; memset(h, -1, sizeof h); for (int i = 1; i <= n - 1; i++) { int a, b, c; cin >> a >> b >> c; add(a, b, c), add(b, a, c); } dfs(1, -1); cout << f[1][m] << endl; return 0; }