#include <bits/stdc++.h>
using namespace std;
inline long long in() {
  int32_t x;
  scanf("%d", &x);
  return x;
}
inline long long lin() {
  long long x;
  scanf("%lld", &x);
  return x;
}
const long long maxn = 1e6 + 10;
const long long mod = 1e9 + 7;
const long long infll = 2e18 + 10;
const long long inf = 1e9 + 10;
long long a[maxn];
vector<long long> g[maxn];
long long father[maxn];
long long down[3][maxn];
long long up[3][maxn];
inline void pre_calc(long long node, long long fa = -1) {
  father[node] = fa;
  for (auto u : g[node])
    if (u - fa) pre_calc(u, node);
}
bool mark[3][maxn];
inline void dfs_down(long long node, long long cntUp) {
  if (mark[cntUp][node]) return;
  mark[cntUp][node] = true;
  down[cntUp][node] = a[node] + cntUp;
  for (auto u : g[node]) {
    if (u == father[node]) continue;
    long long newCnt = (cntUp >= 1) + 1;
    dfs_down(u, newCnt);
    down[cntUp][node] = max(down[cntUp][node], down[newCnt][u]);
  }
}
long long pref[maxn], suf[maxn];
inline void dfs_up(long long node, long long cntDown) {
  if (mark[cntDown][node]) return;
  mark[cntDown][node] = true;
  up[cntDown][node] = max(a[node] + cntDown, up[cntDown][node]);
  long long newCnt = 1 + (cntDown >= 1);
  dfs_up(node, newCnt);
  for (long long i = 0; i < g[node].size(); i++) {
    long long u = g[node][i];
    if (u == father[node])
      pref[i] = (i ? pref[i - 1] : -inf);
    else
      pref[i] = max((i ? pref[i - 1] : -inf), down[2][u]);
  }
  for (long long i = (long long)g[node].size() - 1; i >= 0; i--) {
    long long u = g[node][i];
    if (u == father[node])
      suf[i] = ((i + 1) < g[node].size() ? suf[i + 1] : -inf);
    else
      suf[i] = max(((i + 1) < g[node].size() ? suf[i + 1] : -inf), down[2][u]);
  }
  for (long long i = 0; i < g[node].size(); i++) {
    long long u = g[node][i];
    if (u == father[node]) continue;
    long long Maximum = max((i ? pref[i - 1] : -inf),
                            (i + 1) < g[node].size() ? suf[i + 1] : -inf);
    Maximum = max(Maximum, up[newCnt][node]);
    up[cntDown][u] = max(up[cntDown][u], Maximum);
  }
  for (auto u : g[node])
    if (u - father[node]) dfs_up(u, cntDown);
}
int32_t main() {
  long long n = in();
  for (long long i = 0; i < n; i++) {
    a[i] = in();
    for (long long j = 0; j < 3; j++) down[j][i] = up[j][i] = -inf;
  }
  for (long long i = 0; i < n - 1; i++) {
    long long v = in() - 1, u = in() - 1;
    g[v].push_back(u);
    g[u].push_back(v);
  }
  pre_calc(0);
  for (long long i = 0; i <= 2; i++)
    for (long long node = 0; node < n; node++) dfs_down(node, i);
  memset(mark, 0, sizeof mark);
  for (long long i = 0; i <= 2; i++)
    for (long long node = 0; node < n; node++) dfs_up(node, i);
  long long res = inf + maxn;
  for (long long i = 0; i < n; i++) {
    res = min(res, max(up[0][i], down[0][i]));
  }
  cout << res << endl;
}
