2012-05-30 21:29:40Morris

[ITSA][DP][15th 精] Problem 4. Group without direct leaders

Problem 4. Group without direct leaders
(Time Limit: 5 seconds)
Problem Description
In X company, everyone, except the CEO, has a direct leader. There are n persons in the company and everyone has a unique ID from 0 to n-1. The ID of the CEO is 0, and the ID of any one is larger than the one of his/her direct leader. Besides everyone has a weight which is a positive integer. We want to find a group of weight as large as possible such that no one is the direct leader of any other in the group.

Input File Format
The input contains three lines. The first line is an integers n, 1<n<=90000, which indicates the number of persons in the company. The second line consists of n integers which are the weights of person 0,1,…, n-1, respectively. The total weight is no more than 100,000,000. In the third line, there are n-1 integers which are the ID of direct leaders of person 1, 2,…, n-1, respectively.

Output Format
Output the maximum number of person we can group in one line.

Example

Sample Input:

5
10 20 30 40 50
0 1 1 3

Sample Output:
90

做法 : dp

全部題目就這題比較難, 其他題都普普, 當然如果有需要者, 可以留言向我要求,

由於是樹形, 因此在劃分的時候與子樹的最佳化去做延伸即可,

狀態記錄 dp[subtree_node][choose_or_not],

這題故意設計得很好, 以至於一個迴圈就可以做出 dp 了, 否則要在重新整理一棵樹,
或者是 BFS 去做更新, 剩下的狀態轉移過程, 希望你從程式碼中看出

#include <stdio.h>

#include <vector>
using namespace std;
struct Arc {
    int to;
};
int n, A[90000], B[90000];
int main() {
    int i;

    while(scanf("%d", &n) == 1) {
        for(i = 0; i < n; i++)
            scanf("%d", &A[i]);
        vector<Arc> mylink[90000];
        Arc tmp;
        for(i = 1; i < n; i++) {
            scanf("%d", &B[i]);
            tmp.to = i;
            mylink[B[i]].push_back(tmp);
        }
        int dp[90000][2] = {};
        for(i = n-1; i >= 0; i--) {
            int sum1 = 0, sum2 = 0;
            for(vector<Arc>::iterator j = mylink[i].begin(); j != mylink[i].end(); j++) {
                sum1 += dp[j->to][0] > dp[j->to][1] ? dp[j->to][0] : dp[j->to][1];
                sum2 += dp[j->to][1];
            }
            dp[i][0] = sum2+A[i];
            dp[i][1] = sum1;
        }
        int ans = dp[0][0] > dp[0][1] ? dp[0][0] : dp[0][1];
        printf("%d\n", ans);
    }
    return 0;
}