Vijos P1706 舞會

舞會

Description

Arthur公司是一個等級森嚴的公司,它們有着嚴格的上司與下屬的關係,公司以總裁爲最高職位,他有若干個下屬,他的下屬又有若干個下屬,他的下屬的下屬又有若干個下屬……現接近年尾,公司組織團拜活動,活動中有一部分是自由舞會,公司的每個職員都有一個搞笑值,現要你制定一套哪些人上臺的方案,使得臺上所有演員的搞笑值最大。當然,職員們是不會和他們的頂頭上司一起上臺

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章