由于上司的关系构成了一颗树,于是我们可以从树形dp的角度去考虑问题。不妨用f[cur][0]表示不选当前节点时这棵子树value的最大值,f[cur][1]表示选当前节点时这棵子树value的最大值,那么如果不选当前节点,它的子节点就可选也可不选,因此f[cur][0]要加上所有子节点x的Max{f[x][1],f[x][0]},而如果选当前节点,它的子节点必然不能选,因此f[cur][1]要加上所有子节点x的f[x][0]以及当前节点本身的value。
#include<stdio.h> #include<string.h> #define MAXD 6010 int N, first[MAXD], next[MAXD], v[MAXD], e, dgr[MAXD]; int a[MAXD], f[MAXD][2]; int Max(int x, int y) { return x > y ? x : y; } void add(int x, int y) { v[e] = y; next[e] = first[x], first[x] = e ++; } void init() { int i, L, K; memset(dgr, 0, sizeof(dgr)); memset(first, -1, sizeof(first)); e = 0; for(i = 1; i <= N; i ++) scanf("%d", &a[i]); for(;;) { scanf("%d%d", &L, &K); if(!L && !K) break; add(K, L), ++ dgr[L]; } } void dp(int cur) { int i, max, sum; max = sum = 0; for(i = first[cur]; i != -1; i = next[i]) { dp(v[i]); max += Max(f[v[i]][0], f[v[i]][1]); sum += f[v[i]][0]; } f[cur][1] = sum + a[cur]; f[cur][0] = max; } void solve() { int i, j, k, ans = 0; for(i = 1; i <= N; i ++) if(dgr[i] == 0) { dp(i); ans += Max(f[i][0], f[i][1]); } printf("%d\n", ans); } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }