#include using namespace std; using ll = long long; template istream& operator >> (istream& is, vector& vec) { for(T& x : vec) is >> x; return is; } // atcoder::internal::csr の模倣 template struct csr { struct Node { csr* g; int u; template void emplace_back(Args&&... args){ g->add_edge(u, T(std::forward(args)...)); } auto begin(){ return g->E.begin() + g->start[u]; } auto end(){ return g->E.begin() + g->start[u + 1]; } int size(){ return g->start[u + 1] - g->start[u]; } T& operator[](int p){ return *(begin() + p); } }; int N; std::vector start; std::vector E; std::vector> edge; csr(int n) : N(n), start(n + 1) {edge.reserve(n);} void add_edge(int u, T v){ assert(0 <= u && u < N); start[u + 1]++; edge.emplace_back(u, v); } void build(){ E.resize(edge.size()); for(int i = 0; i < N; i++) start[i + 1] += start[i]; auto cnt = start; for(auto [u, v] : edge) E[cnt[u]++] = v; } const int size() {return N;} Node operator[](int u) {return Node{this, u};} }; int main(){ ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; vector a(n); cin >> a; csr g(n); for(int i = 1; i < n; i++){ int u, v; cin >> u >> v; u--, v--; if(a[u] < a[v]) g[u].emplace_back(v); if(a[v] < a[u]) g[v].emplace_back(u); } g.build(); vector dp(n, -1); auto dfs = [&](auto dfs, int v) -> ll { if(dp[v] != -1) return dp[v]; ll mx = 0; for(auto &&u : g[v]) mx = max(mx, dfs(dfs, u)); return dp[v] = mx + a[v]; }; ll ans = 0; for(int i = 0; i < n; i++) ans = max(ans, dfs(dfs, i)); cout << ans << '\n'; }