舞會
Description
Input
第一行一個整數N,表示這個公司總共的職員個數。
接下來一行有N個整數,由空格隔開,第i個整數表示職員i的搞笑值Ai(-1327670≤Ai≤1327670)。
接下來N-1行,每行一個1到N的整數,第i個整數表示職員i+1的頂頭上司是誰,當然總裁就是職員1。
Output
一個整數,表示臺上所有職員搞笑值之和的最大值。
Sample Input
7 1 1 1 1 1 1 1 1 1 5 1 4 4
Sample Output
5
Answer
/**
這是一個樹形DP
設dp[i][0]爲在下標爲i的節點的子樹上得到的最大值(不取根節點i)
設dp[i][1]爲在下標爲i的節點的子樹上得到的最大值(取根節點i)
那麼dp[i][0] += max(dp[q][0],dp[q][1]); ==>q∈{i點的子節點}
而dp[i][1] += dp[q][0]; ==>q∈{i點的子節點}
記憶化搜索即可
**/
#include
#define maxn (5000 + 10)
using namespace std;
int dp[maxn][2];
vector Vec[maxn];
int va[maxn];
int n;
void DFS(int p) {
// printf("%d \n",p);
if(p > n) return;
if(dp[p][0] != -1 || dp[p][1] != -1) return;
if(Vec[p].size() == 0) {
dp[p][1] = va[p];
dp[p][0] = 0;
return ;
}
for(int i = 0; i < Vec[p].size(); i ++) DFS(Vec[p][i]);
dp[p][0] = 0;
dp[p][1] = va[p];
for(int i = 0; i < Vec[p].size(); i ++) {
int q = Vec[p][i];
dp[p][0] += max(dp[q][0],dp[q][1]);
dp[p][1] += dp[q][0];
}
}
int main() {
// freopen("in.txt","r",stdin);
memset(dp,-1,sizeof(dp));
scanf("%d",&n);
for(int i = 1; i <= n; i ++) {
scanf("%d",&va[i]);
}
for(int i = 1; i <= n; i ++) {
if(i == 1) continue;
int pre;
scanf("%d",&pre);
Vec[pre].push_back(i);
}
DFS(1);
printf("%d\n",max(dp[1][0],dp[1][1]));
return 0;
}