1. 程式人生 > >SGU 143. Long Live the Queen(樹形DP)

SGU 143. Long Live the Queen(樹形DP)

The Queen of Byteland is very loved by her people. In order to show her their love, the Bytelanders have decided to conquer a new country which will be named according to the queen's name. This new country contains N towns. The towns are connected by bidirectional roads and there is exactly ONE path between any two towns, walking on the country's roads. For each town, the profit it brings to the owner is known. Although the Bytelanders love their queen very much, they don't want to conquer all the N

 towns for her. They will be satisfied with a non-empty subset of these towns, with the following 2 properties: there exists a path from every town in the subset to every other town in the subset walking only through towns in the subset and the profit of the subset is maximum. The profit of a subset of the N
 towns is equal to the sum of the profits of the towns which belong to the subset. Your task is to find the maximum profit the Bytelanders may get.

Input

The first line of input will contain the number of towns N (1<=N<=16 000). The second line will contain N integers: the profits for each town, from 1

 to N. Each profit is an integer number between -1000 and 1000. The next N-1 lines describe the roads: each line contains 2 integer numbers a and b, separated by blanks, denoting two different towns between which there exists a road.

Output

The output should contain one integer number: the maximum profit the Bytelanders may get.

Sample Input

5
-1 1 3 1 -1
4 1
1 3
1 2
4 5

Sample Output

4

題意:給你一棵樹,樹上每一個點都有一個權值,有正有負,讓你從n個點中選出若干個聯通的點(選出的這些點必須在原圖中都聯通),使得總權值最大。

思路:樹形DP,dp[i][0]表示選到節點i,且節點i這個節點不選,dp[i][1]表示節點i這個點選。

轉移:如果節點i選的話,那麼和他相連的點可選可不選,那麼我們就把正的都加上,如果這個節點不選的話,那麼我們只能從和他相連的節點中選一個最大的。

有一個坑點,就是至少要選一個點,如果所有點的權值都是負數,那麼我們就選一個最大的。

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long

using namespace std;

const int inf = 1e8;

int a[16010];
int dp[16010][2];
vector<int> e[16010];

void dfs(int x,int pre)
{
    dp[x][1] = a[x];
    dp[x][0] = 0;
    for(int i=0;i<e[x].size();i++)
    {
        int xx = e[x][i];
        if(xx == pre)
            continue;
        dfs(xx,x);
        dp[x][1] = max(dp[x][1],dp[x][1] + dp[xx][1]);
        dp[x][0] = max(dp[x][0],max(dp[xx][1],dp[xx][0]));
    }
}
int main(void)
{
    int n,i,j;
    scanf("%d",&n);
    int flag = 0;
    int maxn = -inf;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        maxn = max(maxn,a[i]);
        if(a[i] >= 0)
            flag = 1;
    }
    for(i=0;i<n-1;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    if(flag == 0)
    {
        printf("%d\n",maxn);
    }
    else
    {
        dfs(1,-1);
        printf("%d\n",max(dp[1][0],dp[1][1]));
    }

    return 0;
}