—9月13日
1.树形DP问题
题目:acm.hdu.edu.cn/showproblem.php?pid=1520
题意:一棵树,每个节点有一个value,父子节点不能同时选择,如何选择节点使sum最大。
分析: dp[u][0] += max(dp[j][0], dp[j][1]), dp[u][1] += dp[j][0]; (0表示不选u节点,1表示选择,j为u的子节点)
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <set> #include <utility> #include <map> #include <cstdlib> #include <queue> #include <vector> #include <numeric> #include <list> #include <bitset> #include <exception> #include <istream> #include <ostream> #include <stdexcept> #include <functional> #include <typeinfo> #define LL long long int using namespace std; int val[6010]; int dp[6010][2]; vector<int> vec[6010]; int in[6010]; int dfs(int u) { dp[u][0] = 0, dp[u][1] = val[u]; for (int i = 0; i < vec[u].size(); ++i) { int j = vec[u][i]; dfs(j); dp[u][0] += max(dp[j][0], dp[j][1]); dp[u][1] += dp[j][0]; } return max(dp[u][0], dp[u][1]); } int main() { int n; while (~scanf("%d", &n)) { for (int i = 1; i <= n; ++i) scanf("%d", &val[i]), vec[i].clear(), in[i] = 0; int u, v; while (scanf("%d%d", &u, &v) && u+v) { vec[v].push_back(u); in[u]++; } int ans = 0; for (int i = 1; i <=n; ++i) { if (in[i] == 0) { ans += dfs(i); break; } } printf("%d\n", ans); } return 0; }