vue 上傳外掛
阿新 • • 發佈:2022-11-30
題目連結:https://www.acwing.com/problem/content/287/
題目描述
Ural 大學有 N 名職員,編號為 1∼N。
他們的關係就像一棵以校長為根的樹,父節點就是子節點的直接上司。
每個職員有一個快樂指數,用整數 Hi 給出,其中 1≤i≤N。
現在要召開一場週年慶宴會,不過,沒有職員願意和直接上司一起參會。
在滿足這個條件的前提下,主辦方希望邀請一部分職員參會,使得所有參會職員的快樂指數總和最大,求這個最大值。
輸入描述
第一行一個整數 N。
接下來 N 行,第 i 行表示 i 號職員的快樂指數 Hi。
接下來 N−1 行,每行輸入一對整數 L,K,表示 K 是 L 的直接上司。
輸出描述
輸出最大的快樂指數。
1≤N≤6000
−128≤Hi≤127
示例
輸入
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
輸出
5
分析
約定
我們記每個人的歡樂度為happy[i]。
狀態表示
職員間的從屬關係可以用一棵樹來表示,每一位員工的父節點為其直接上司。
我們用f[i][0]表示第i個節點代表的員工不參加舞會的情況下,以第i個節點為根節點的子樹參與舞會情況的最大歡樂度和。
用f[i][1]表示第i個節點代表的員工參加舞會的情況下,以第i個節點為根節點的子樹參與舞會情況的最大歡樂度和。
狀態計算
由題意得父節點與子節點得關係如下:
- 若父節點參與舞會,則兒子節點均不能參與舞會
- 若父節點不參與舞會,則兒子節點參與舞會沒有限制,參不參與都行
因此,我們可以得到狀態轉移方程:
f[i][0] = max(f[j1][0],f[j1][1]) + max(f[j2][0],f[j2][1]) + ··· (j1,j2,···為其兒子節點)
f[i][1] = happy[i] + f[j1][0] + f[j2][0] + ···· (j1,j2,···為其兒子節點)
各狀態的求解採用DFS實現,類似記憶化搜尋。
AC程式碼
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N = 6010; int n; int happy[N]; int h[N], e[2 * N], ne[2 * N], idx; //鄰接表儲存樹 int f[N][2]; int has_father[N]; void add(int x, int y) { e[idx] = y; ne[idx] = h[x]; h[x] = idx; idx++; } void dfs(int u) { f[u][1] = happy[u]; for (int i = h[u]; i != -1; i = ne[i]) { dfs(e[i]); f[u][0] += max(f[e[i]][0], f[e[i]][1]); f[u][1] += f[e[i]][0]; } } int main() { memset(h, -1, sizeof(h)); cin >> n; for (int i = 1; i <= n; i++) cin >> happy[i]; for (int i = 0; i < n - 1; i++) { int x, y; cin >> x >> y; add(y, x); has_father[x] = y; } int root = 1; while (has_father[root]) //確定根節點 root = has_father[root]; dfs(root); cout << max(f[root][0], f[root][1]) << endl; return 0; }