【题目链接】
【算法】
树形DP
令f[i][0]表示 : 以i为根的子树中,若i不参加宴会,所能获得的最大愉悦值
f[i][1]表示 : 以i为根的子树中,若i参加宴会,所能获得的最大愉悦值
那么,如果i不参加宴会,它的下属就可以参加宴会,也可以不参加宴会,因此 :
f[i][0] = sigma( max(f[j][0],f[j][1]) ) (j为i的子节点)
如果i参加宴会,它的下属必然不能参加宴会,因此 :
f[i][1] = Ri + sigma( f[j][0] ) (j为i的子节点)
最后,答案为max(f[root][0],f[root][1])(root为根节点)
【代码】
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXN 6010 int i,n,u,v,root; vector<int> e[MAXN]; int val[MAXN],fa[MAXN],f[MAXN][2]; inline void dfs(int x) { int i,y; f[x][1] = val[x]; for (i = 0; i < e[x].size(); i++) { y = e[x][i]; dfs(y); f[x][0] += max(f[y][0],f[y][1]); f[x][1] += f[y][0]; } } int main() { while (scanf("%d",&n) != EOF) { for (i = 1; i <= n; i++) { e[i].clear(); f[i][0] = f[i][1] = 0; } for (i = 1; i <= n; i++) scanf("%d",&val[i]); for (i = 1; i < n; i++) { scanf("%d%d",&u,&v); e[v].push_back(u); fa[u] = v; } scanf("%d%d",&u,&v); for (i = 1; i <= n; i++) { if (!fa[i]) root = i; } dfs(root); printf("%d ",max(f[root][0],f[root][1])); } return 0; }