題面c++
樹形\(\text{DP}\)入門題。spa
咱們設\(dp[i][0/1]\)表示第\(i\)個節點選\(/\)不選的最大快樂指數。code
狀態轉移方程:
\(dp[i][0]=a[i]+\sum_{v∈son[u]}dp[v][1]\),其中\(a[i]\)爲每一個員工的快樂指數。
\(dp[i][1]=\sum_{v∈son[u]}\max{(dp[v][1],dp[v][0])}\)get
答案爲\(\max{(dp[rt][0],dp[rt][1])}\),其中\(rt\)爲沒有上司的員工。it
轉移一下便可。入門
#include <bits/stdc++.h> #define itn int #define gI gi using namespace std; inline int gi() { int f = 1, x = 0; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();} while (c >= '0' && c <= '9') x = x * 10 + (c ^ 48), c = getchar(); return f * x; } const int maxn = 6003; int n, a[maxn], tot, head[maxn], ver[maxn * 2], nxt[maxn], ans, vis[maxn], rt; int dp[maxn][2];//0:xuan 1:buxuan inline void add(int u, int v) { ver[++tot] = v, nxt[tot] = head[u], head[u] = tot; } void dfs(int u, int f) { dp[u][0] = a[u]; for (int i = head[u]; i; i = nxt[i]) { int v = ver[i]; if (v == f) continue; dfs(v, u); dp[u][0] += dp[v][1]; dp[u][1] += max(dp[v][0], dp[v][1]);//狀態轉移 } } int main() { n = gi(); for (int i = 1; i <= n; i+=1) a[i] = gi(); for (int i = 1; i < n; i+=1) { int u = gi(), v = gi(); add(u, v); add(v, u); vis[u] = 1; } int h = gi(), o = gi(); for (int i = 1; i <= n; i+=1) if (!vis[i]) {rt = i; break;}//找到根節點,即沒有上司的員工編號 dfs(rt, 0); printf("%d\n", max(dp[rt][0], dp[rt][1]));//答案就是根節點選/不選取max return 0; }
由此,咱們能夠得出樹形\(\text{DP}\)的狀態的基本形式:class
\(dp[i][…]\)表示第\(i\)個節點的狀態。總結