#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 INF = (1LL << 62); vector ans(N, -INF); // パスの片方の端点 s を全探索 for (int s = 0; s < N; ++s) { vector par(N, -1), dep(N); vector sum(N), best(N); vector order = {s}; sum[s] = A[s]; // s を根とした木を作る for (int i = 0; i < (int)order.size(); ++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.push_back(u); } } // s -> v を旅したときの得点 for (int v : order) { ll d = dep[v]; best[v] = sum[v] - d * (d + 1) / 2; } // 部分木内の最大値 for (int i = N - 1; i > 0; --i) { int v = order[i]; best[par[v]] = max(best[par[v]], best[v]); } for (int r = 0; r < N; ++r) { ans[r] = max(ans[r], best[r]); } } cout << *min_element(ans.begin(), ans.end()) << '\n'; }