题目中的意思翻译过来其实是在一颗数上相邻的节点只能选择一个,那么最大的和为多少。
那么对于每一个节点来说就有选与不选两种状态:dp[i][0/1]
如果选的话那么以这个节点为根的子树最大和为:dp[i][1] = (f[i]+(所有子树和)dp[u][0]);
如果不选的话那么对于子树来说就有选与不选两种情况,两种情况选大的就行。:dp[i][0] = (所有子树和)max(dp[u][0], dp[u][1]);
//题目中的意思翻译过来其实是在一颗数上相邻的节点只能选择一个,那么最大的和为多少。
//那么对于每一个节点来说就有选与不选两种状态:dp[i][0/1]
//如果选的话那么以这个节点为根的子树最大和为:dp[i][1] = (f[i]+(所有子树和)dp[u][0]);
//如果不选的话那么对于子树来说就有选与不选两种情况,两种情况选大的就行。:dp[i][0] = (所有子树和)max(dp[u][0], dp[u][1]);
#include <bits/stdc++.h>


using namespace std;
const int maxn = 6000+10;
int f[maxn];
vector<int> v[maxn];
int dp[maxn][2];

void dfs(int x, int fa) {
    int len = v[x].size();
    dp[x][1] = f[x];
    for (int i=0;i<len;i++) {
        int next = v[x][i];
        if (next == fa) continue;
        dfs(next, x);
        dp[x][1] += dp[next][0];
        dp[x][0] += max(dp[next][0], dp[next][1]);
    }
}

int main() {
    int n;
    int x, y;
    cin>>n;
    for (int i=1;i<=n;i++) {
        cin>>f[i];
    }
    for (int i=1;i<=n;i++) {
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1, 0);
    cout<<(dp[1][0]>dp[1][1]? dp[1][0]:dp[1][1]);
    return 0;
}