#include <bits/stdc++.h>
using namespace std;
const int maxn = 500005, inf = 0x3F3F3F3F;
int n, m, tot, lnk[maxn], w[maxn], son[maxn * 2], nxt[maxn * 2], B[maxn],
    Min[maxn], Sec[maxn], tot2, lnk2[maxn], son2[maxn], nxt2[maxn], BMax,
    ans = inf;
inline char nc() {
  static char buf[8388608], *L = buf, *R = buf;
  return L == R && (R = (L = buf) + fread(buf, 1, 8388608, stdin), L == R)
             ? EOF
             : *L++;
}
inline int read() {
  int ret = 0, f = 1;
  char ch = nc();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -f;
    ch = nc();
  }
  while (ch >= '0' && ch <= '9') {
    ret = ret * 10 + ch - '0';
    ch = nc();
  }
  return ret * f;
}
inline void add_e(int x, int y) {
  tot++;
  son[tot] = y;
  nxt[tot] = lnk[x];
  lnk[x] = tot;
}
inline void add_e2(int x, int y) {
  tot2++;
  son2[tot2] = y;
  nxt2[tot2] = lnk2[x];
  lnk2[x] = tot2;
}
struct SegmentTree {
  struct Node {
    int Min, Tag;
  } Tree[maxn * 4];
  inline void PushUp(int rt) {
    Tree[rt].Min =
        (Tree[rt << 1].Min < Tree[rt << 1 | 1].Min ? Tree[rt << 1].Min
                                                   : Tree[rt << 1 | 1].Min);
  }
  inline void PushDown(int rt) {
    if (!Tree[rt].Tag) return;
    Tree[rt << 1].Min += Tree[rt].Tag;
    Tree[rt << 1 | 1].Min += Tree[rt].Tag;
    Tree[rt << 1].Tag += Tree[rt].Tag;
    Tree[rt << 1 | 1].Tag += Tree[rt].Tag;
    Tree[rt].Tag = 0;
  }
  inline void RangeUpdate(int RR, int delta, int L = 1, int R = m, int rt = 1) {
    if (RR == m) {
      Tree[rt].Min += delta;
      Tree[rt].Tag += delta;
      return;
    }
    while (L <= R && L <= RR) {
      PushDown(rt);
      int M = (L + R) >> 1;
      if (M <= RR) {
        Tree[rt << 1].Min += delta;
        Tree[rt << 1].Tag += delta;
        L = M + 1;
        rt = rt << 1 | 1;
      } else {
        R = M;
        rt = rt << 1;
      }
    }
    while (rt > 1) {
      rt >>= 1;
      PushUp(rt);
    }
  }
  void Build(int L = 1, int R = m, int rt = 1) {
    if (L == R) {
      Tree[rt].Min = L - m - 1;
      return;
    }
    int M = (L + R) >> 1;
    Build(L, M, rt << 1);
    Build(M + 1, R, rt << 1 | 1);
    PushUp(rt);
  }
  inline int Query(int pos, int L = 1, int R = m, int rt = 1) {
    if (L == R) return Tree[rt].Min;
    int M = (L + R) >> 1;
    PushDown(rt);
    if (pos <= M)
      return Query(pos, L, M, rt << 1);
    else
      return Query(pos, M + 1, R, rt << 1 | 1);
  }
} T;
void Build(int now, int fa, int id, int mi, int se) {
  if (w[now] <= mi) {
    se = mi;
    mi = w[now];
    id = now;
  } else if (w[now] < se)
    se = w[now];
  Min[now] = mi;
  Sec[now] = se;
  add_e2(id, now);
  for (int i = lnk[now]; i; i = nxt[i])
    if (son[i] != fa) Build(son[i], now, id, mi, se);
}
inline void Modify(int num, int delta) {
  int L = 1, R = m, mid;
  while (L <= R) {
    mid = (L + R) >> 1;
    B[mid] <= num ? L = mid + 1 : R = mid - 1;
  }
  if (R >= 1) T.RangeUpdate(R, delta);
}
inline void Solve(int now, int fa) {
  if (w[now] < BMax && BMax - w[now] < ans) {
    for (int i = lnk2[now]; i; i = nxt2[i]) {
      Modify(Min[now], -1);
      Modify(min(Sec[son2[i]], BMax), 1);
    }
    if (T.Tree[1].Min >= 0) ans = BMax - w[now];
    for (int i = lnk2[now]; i; i = nxt2[i]) {
      Modify(Min[now], 1);
      Modify(min(Sec[son2[i]], BMax), -1);
    }
  }
  for (int i = lnk[now]; i; i = nxt[i])
    if (son[i] != fa) Solve(son[i], now);
}
int main() {
  n = read();
  for (int i = 1; i <= n; i++) w[i] = read();
  for (int i = 2; i <= n; i++) {
    int a = read(), b = read();
    add_e(a, b);
    add_e(b, a);
  }
  m = read();
  for (int i = 1; i <= m; i++) B[i] = read();
  sort(B + 1, B + 1 + m);
  Build(1, 0, 0, inf, inf);
  T.Build();
  for (int i = 1; i <= n; i++) Modify(Min[i], 1);
  for (int i = m; i; i--)
    if (T.Query(i) < 0) {
      BMax = B[i];
      break;
    }
  if (BMax)
    Solve(1, 0);
  else
    ans = 0;
  printf("%d\n", ans == inf ? -1 : ans);
  return 0;
}
