#include <bits/stdc++.h>
using namespace std;
int tree[100001],dp[100001],p[100001],n,x,y,mask[100001]={0},sons[100001]={0};
int rdp1[100001],rdp2[100001]={0},vis[100001]={0};
//树形dp,从下往上更新,具体见算法入门经典
//节点选择除了自上而下和枚举子子的另一种解法:
//用F[i]表示i这条根要,G[i]表示不要(也可以用f[i][1,0]来表示
// f[root]+=g[ee[i].y];
//g[root]+=max(f[ee[i].y],g[ee[i].y]);
//要了就子不能要,没要,要不要都行
vector<int> points[100001];
queue<int> q;
void build(){
queue<int> qq;
qq.push(1);
vis[1]=1;
while(!qq.empty()){
int pp=qq.front();
qq.pop();
for(vector<int>::iterator i=points[pp].begin();i!=points[pp].end();i++){
if(vis[*i]==0){
vis[*i]=1;
qq.push(*i);
p[*i]=pp;
sons[pp]++;
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>tree[i];
rdp1[i]=tree[i];
p[i]=-1;
}
for(int i=1;i<n;i++){
cin>>x>>y;
points[x].push_back(y);
points[y].push_back(x);
mask[x]++;
mask[y]++;
}
build();
for(int i=1;i<=n;i++)
if(mask[i]==1)
q.push(i);
while(!q.empty()){
int point=q.front();
q.pop();
dp[point]=max(rdp1[point],rdp2[point]);
if(p[point]!=-1){
rdp2[p[point]]+=dp[point];
if(p[p[point]]!=-1) rdp1[p[p[point]]]+=dp[point];
sons[p[point]]--;
if(sons[p[point]]==0) q.push(p[point]);
}
}
cout<<dp[1]<<endl;
return 0;
}