int n, w[N], dp[N][2]; voiddfs(int u){ dp[u][1] = w[u]; for (auto v : E[u]) { dfs(v); dp[u][0] += max(dp[v][0], dp[v][1]); dp[u][1] += dp[v][0]; } } print(max(dp[rt][0], dp[rt][1]));
树,有根有点权。m 元点集S 满足:若子节点∈S,则父节点∈S。最大化S 点权和。(树上背包)
1 2 3 4 5 6 7 8 9 10 11 12
int n, m, w[N], dp[N][M]; voiddfs(int u){ dp[u][1] = w[u]; for (auto v : E[u]) { dfs(v); for (int k = m; k >= 1; --k) { for (int i = k; i <= m; ++i) dp[u][i] = max(dp[u][i], dp[u][k] + dp[v][i-k]); // i>=k } } } printf(dp[st][m]);
树,有点权。最大化子树点权和。(最大点权和)
1 2 3 4 5 6 7 8 9 10 11
int n, w[N], dp[N]; int ans = -0x3f3f3f3f; voiddfs(int u){ dp[u] = w[u]; for (auto v : E[u]) { dfs(v); dp[u] = max(dp[u] + dp[v], dp[u]); } ans = max(ans, dp[u]); } print(ans);
int k, dp[N][K]; ll ans = 0; voiddfs(int u, int fau = -1){ for (auto v : E[u]) { if (v == fau) continue; dfs(v, u); for (int i = 1; i <= k; ++i) ans += dp[v][i - 1] * dp[u][k - i]; for (int i = 1; i <= k; ++i) dp[u][i] += dp[v][i - 1]; } dp[u][0] = 1; ans += dp[u][k]; } print(ans);