#include <bits/stdc++.h>
using namespace std;
int N;
long long A[100100];
vector<int> adj[100100];
long long maxlen[100100];
long long dp[100100][3];
long long getTop2(multiset<long long>& st) {
  long long ret = 0;
  multiset<long long>::iterator it = st.end();
  if (!st.empty()) {
    it--;
    ret += *it;
  }
  if (st.size() >= 2) {
    it--;
    ret += *it;
  }
  return ret;
}
void dfs(int cur, int prv) {
  dp[cur][0] = dp[cur][1] = dp[cur][2] = A[cur];
  multiset<long long> len, path;
  for (auto nxt : adj[cur]) {
    if (nxt == prv) continue;
    dfs(nxt, cur);
    len.insert(maxlen[nxt]);
    path.insert(dp[nxt][0]);
    dp[cur][0] = max(dp[cur][0], dp[nxt][0] + A[cur]);
    dp[cur][1] = max(dp[cur][1], dp[nxt][1] + A[cur]);
    dp[cur][2] = max(dp[cur][2], dp[nxt][2]);
    maxlen[cur] = max(maxlen[cur], maxlen[nxt]);
  }
  maxlen[cur] = max(maxlen[cur], getTop2(path) + A[cur]);
  dp[cur][2] = max(dp[cur][2], getTop2(len));
  for (auto nxt : adj[cur]) {
    if (nxt == prv) continue;
    path.erase(dp[nxt][0]);
    if (!path.empty()) {
      dp[cur][1] = max(dp[cur][1], maxlen[nxt] + *(--path.end()) + A[cur]);
      dp[cur][2] = max(dp[cur][2], dp[nxt][1] + *(--path.end()) + A[cur]);
    }
    dp[cur][2] = max(dp[cur][2], maxlen[nxt] + getTop2(path) + A[cur]);
    path.insert(dp[nxt][0]);
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin >> N;
  for (int i = 1; i <= N; i++) cin >> A[i];
  for (int i = 0, a, b; i < N - 1; i++) {
    cin >> a >> b;
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  dfs(1, 0);
  cout << max(dp[1][0], max(dp[1][1], dp[1][2])) << "\n";
  return 0;
}
