#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using P = pair<int, int>;
constexpr int INF = 1 << 30;
template <typename Monoid>
struct SegmentTree {
 private:
  using F = function<Monoid(Monoid, Monoid)>;
  int N;
  vector<Monoid> node;
  F f;
  Monoid e;

 public:
  SegmentTree() {}
  SegmentTree(F f, Monoid e) : f(f), e(e) {}
  void init(int sz) {
    N = 1;
    while (N < sz) N <<= 1;
    node.assign(2 * N - 1, e);
  }
  void build(vector<Monoid>& v) {
    int sz = int(v.size());
    init(sz);
    for (int i = 0; i < sz; i++) {
      node[i + N - 1] = v[i];
    }
    for (int i = N - 2; i >= 0; i--) {
      node[i] = f(node[i * 2 + 1], node[i * 2 + 2]);
    }
  }
  void update(int k, Monoid x) {
    k += N - 1;
    node[k] = x;
    while (k > 0) {
      k = (k - 1) / 2;
      node[k] = f(node[2 * k + 1], node[2 * k + 2]);
    }
  }
  Monoid query(int a, int b) { return query(a, b, 0, 0, N); }
  Monoid query(int a, int b, int k, int l, int r) {
    if (b <= l || r <= a) return e;
    if (a <= l && r <= b) return node[k];
    Monoid vl, vr;
    vl = query(a, b, 2 * k + 1, l, (l + r) / 2);
    vr = query(a, b, 2 * k + 2, (l + r) / 2, r);
    return f(vl, vr);
  }
};
SegmentTree<int> seg([](int a, int b) { return max(a, b); }, -INF);
vector<vector<int> > g;
vector<int> a;
int main() {
  int n;
  scanf("%d", &n);
  g.resize(n);
  a.resize(n);
  for (int i = 0; i < n; i++) {
    scanf("%d", &a[i]);
  }
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    u--;
    v--;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  seg.build(a);
  int ans = INF;
  for (int i = 0; i < n; i++) {
    int maxi = a[i];
    g[i].push_back(i);
    sort(g[i].begin(), g[i].end());
    int pre = 0;
    for (auto j : g[i]) {
      if (j != i) maxi = max(maxi, a[j] + 1);
      maxi = max(maxi, seg.query(pre, j) + 2);
      pre = j + 1;
    }
    maxi = max(maxi, seg.query(pre, n) + 2);
    ans = min(ans, maxi);
  }
  printf("%d\n", ans);
  return 0;
}
