公司层级構成樹 (根為校長)。每個員工有歡樂度值 (可正負)。派對邀請名單要求:**不同時邀請員工及其直屬上司**。求最大歡樂度和。N ≤ 6000。
DFS 後序遍歷:
答案 = `max(dp[root][0], dp[root][1])`。
#include
#include
#include
#include
using namespace std;
const int MAXN = 6005;
vector G[MAXN];
int dp[MAXN][2], val[MAXN];
int n, root;
bool hasFather[MAXN];
void dfs(int u) {
dp[u][1] = val[u];
dp[u][0] = 0;
for (int v : G[u]) {
dfs(v);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
}
int main() {
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++) {
G[i].clear();
hasFather[i] = false;
}
for (int i = 1; i <= n; i++) scanf("%d", &val[i]);
for (int i = 0; i < n-1; i++) {
int L, K; scanf("%d%d", &L, &K);
G[K].push_back(L); // K 是 L 的上司
hasFather[L] = true;
}
root = 1;
while (hasFather[root]) root++; // 找根
dfs(root);
printf("%d\n", max(dp[root][0], dp[root][1]));
}
return 0;
}
HDU 1520 數據更強,需用**鏈式前向星**存圖避免 vector 慢,並注意遞歸深度 (N=6000 可能棧溢出,建議改迭代或擴大棧)。邏輯完全相同。