#include using namespace std; using ll = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector A(N); for (auto& x : A) cin >> x; vector> G(N); for (int i = 0; i < N - 1; ++i) { int u, v; cin >> u >> v; --u, --v; G[u].push_back(v); G[v].push_back(u); } const ll NEG = -(1LL << 60); vector ans(N, NEG); vector sum(N), best(N); vector par(N), dep(N), order(N); for (int s = 0; s < N; ++s) { int cnt = 1; order[0] = s; par[s] = -1; dep[s] = 0; sum[s] = A[s]; // s を根とする木を構築 for (int i = 0; i < cnt; ++i) { int v = order[i]; for (int u : G[v]) { if (u == par[v]) continue; par[u] = v; dep[u] = dep[v] + 1; sum[u] = sum[v] + A[u]; order[cnt++] = u; } } // s -> v の得点 for (int i = 0; i < N; ++i) { int v = order[i]; ll d = dep[v]; best[v] = sum[v] - d * (d + 1) / 2; } // subtree maximum for (int i = N - 1; i > 0; --i) { int v = order[i]; int p = par[v]; if (best[v] > best[p]) { best[p] = best[v]; } } // 全 r を更新 for (int i = 0; i < N; ++i) { int v = order[i]; if (best[v] > ans[v]) { ans[v] = best[v]; } } } cout << *min_element(ans.begin(), ans.end()) << '\n'; }