#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100010;
int n, total;
int head[MAX_N];
long long value[MAX_N], best[MAX_N], down[MAX_N];
long long prebest[MAX_N], sufbest[MAX_N], predown[MAX_N], ppredown[MAX_N];
long long sufdown[MAX_N], ssufdown[MAX_N], up[MAX_N];
struct Edge {
  int to, next;
} edge[MAX_N * 2];
inline void AddEdge(int from, int to) {
  edge[total].to = to, edge[total].next = head[from];
  head[from] = total++;
}
void dfs(int u, int p) {
  long long Max = 0, MMax = 0;
  for (int i = head[u]; i != -1; i = edge[i].next) {
    int v = edge[i].to;
    if (v == p) continue;
    dfs(v, u);
    if (down[v] > Max) {
      MMax = Max;
      Max = down[v];
    } else if (down[v] > MMax) {
      MMax = down[v];
    }
    best[u] = max(best[u], best[v]);
  }
  down[u] = Max + value[u];
  best[u] = max(best[u], Max + MMax + value[u]);
}
void solve() {
  long long ans = 0;
  queue<pair<int, int> > que;
  que.push(make_pair(1, 0));
  while (!que.empty()) {
    pair<int, int> cur = que.front();
    int u = cur.first, p = cur.second;
    que.pop();
    vector<int> child;
    child.push_back(0);
    for (int i = head[u]; i != -1; i = edge[i].next) {
      int v = edge[i].to;
      if (v != p) child.push_back(v);
    }
    int size = child.size();
    prebest[0] = predown[0] = ppredown[0] = 0;
    for (int i = 1; i < size; ++i) {
      int v = child[i];
      prebest[i] = max(prebest[i - 1], best[v]);
      predown[i] = predown[i - 1], ppredown[i] = ppredown[i - 1];
      if (down[v] > predown[i]) {
        ppredown[i] = predown[i];
        predown[i] = down[v];
      } else if (down[v] > ppredown[i]) {
        ppredown[i] = down[v];
      }
    }
    sufbest[size] = sufdown[size] = ssufdown[size] = 0;
    for (int i = size - 1; i >= 1; --i) {
      int v = child[i];
      sufbest[i] = max(sufbest[i + 1], best[v]);
      sufdown[i] = sufdown[i + 1], ssufdown[i] = ssufdown[i + 1];
      if (down[v] > sufdown[i]) {
        ssufdown[i] = sufdown[i];
        sufdown[i] = down[v];
      } else if (down[v] > ssufdown[i]) {
        ssufdown[i] = down[v];
      }
    }
    for (int i = 1; i < size; ++i) {
      int v = child[i];
      long long another =
          up[u] + value[u] + max(predown[i - 1], sufdown[i + 1]);
      another = max(another, value[u] + predown[i - 1] + ppredown[i - 1]);
      another = max(another, value[u] + sufdown[i + 1] + ssufdown[i + 1]);
      another = max(another, value[u] + predown[i - 1] + sufdown[i + 1]);
      another = max(another, max(prebest[i - 1], sufbest[i + 1]));
      ans = max(ans, another + best[v]);
    }
    for (int i = 1; i < size; ++i) {
      int v = child[i];
      up[v] = value[u] + max(up[u], max(predown[i - 1], sufdown[i + 1]));
      que.push(make_pair(v, u));
    }
  }
  printf("%lld\n", ans);
}
int main() {
  while (~scanf("%d", &n)) {
    for (int i = 1; i <= n; ++i) {
      scanf("%lld", &value[i]);
    }
    memset(head, -1, sizeof(head));
    total = 0;
    for (int i = 1; i < n; ++i) {
      int u, v;
      scanf("%d%d", &u, &v);
      AddEdge(u, v);
      AddEdge(v, u);
    }
    memset(best, 0, sizeof(best));
    memset(down, 0, sizeof(down));
    memset(up, 0, sizeof(up));
    dfs(1, 0);
    solve();
  }
  return 0;
}
