1. 程式人生 > >[Luogu P1352] 沒有上司的舞會

[Luogu P1352] 沒有上司的舞會

洛谷傳送門

題目描述

某大學有NN個職員,編號為1N1\sim N。他們之間有從屬關係,也就是說他們的關係就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個週年慶宴會,宴會每邀請來一個職員都會增加一定的快樂指數RiR_i,但是呢,如果某個職員的上司來參加舞會了,那麼這個職員就無論如何也不肯來參加舞會了。所以,請你程式設計計算,邀請哪些職員可以使快樂指數最大,求最大的快樂指數。

輸入輸出格式

輸入格式:

第一行一個整數N。(1N60001\le N\le 6000)

接下來NN行,第i+1i+1行表示i號職員的快樂指數RiR_i。(128Ri127

-128\le Ri\le 127)

接下來N1N-1行,每行輸入一對整數L,KL,K。表示KKLL的直接上司。

最後一行輸入000\ 0

輸出格式:

輸出最大的快樂指數。

輸入輸出樣例

輸入樣例#1:

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

輸出樣例#1:

5

解題分析

樹上0/1DP0/1DP。 設dp[i][0]dp[i][0]表示不選這個點, dp[i][1]dp[i][1]表示選這個點, 那麼轉移方程為: dp[i][0]=j,json[i]max(dp[j][0],dp[j][

1])dp[i][1]=j,json[i]dp[j][0]+val[i] dp[i][0]=\sum_{j,j\in son[i]}max(dp[j][0],dp[j][1]) \\ dp[i][1]=\sum_{j,j\in son[i]}dp[j][0]+val[i] 程式碼如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include
<cctype>
#include <algorithm> #include <cmath> #define R register #define IN inline #define W while #define gc getchar() #define MX 10500 bool neg; template <class T> IN void in(T &x) { x = 0; R char c = gc; for (; !isdigit(c); c = gc) if (c == '-') neg = true; for (; isdigit(c); c = gc) x = (x << 1) + (x << 3) + c - 48; if(neg) neg = false, x = -x; } int dot, cnt; int dp[MX][2], head[MX], val[MX], deg[MX]; struct Edge {int to, nex;} edge[MX << 1]; IN void add(R int from, R int to) {edge[++cnt] = {to, head[from]}, head[from] = cnt;} void DFS(R int now) { dp[now][0] = 0, dp[now][1] = val[now]; for (R int i = head[now]; i; i = edge[i].nex) { DFS(edge[i].to); dp[now][0] += std::max(dp[edge[i].to][0], dp[edge[i].to][1]); dp[now][1] += dp[edge[i].to][0]; } } int main(void) { int a, b; in(dot); for (R int i = 1; i <= dot; ++i) in(val[i]); for (R int i = 1; i < dot; ++i) in(a), in(b), add(b, a), ++deg[a]; for (R int i = 1; i <= dot; ++i) if(!deg[i]) {DFS(i); printf("%d", std::max(dp[i][0], dp[i][1])); break;} }