#include <bits/stdc++.h>
using namespace std;
int main() {
std::ios_base::sync_with_stdio(false);
int n; cin >> n;
vector<int64_t> w(n+1);
int64_t tw = 0;
for (int i = 1; i <= n; ++i) {
cin >> w[i]; tw += w[i];
}
vector<vector<int>> adj(n+1);
for (int i = 1; i <= n - 1; ++i) {
int u, v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u);
}
vector<int64_t> pw(n+1);
vector<pair<int, int>> etime(n+1);
vector<int> etour;
function<int64_t(int, int)> dfs1 = [&] (int u, int from) {
int enter = etour.size();
etour.push_back(u);
int64_t ans = w[u];
for (auto v : adj[u]) if (v != from) ans += dfs1(v, u);
int left = etour.size();
etime[u] = {enter, left};
pw[u] = tw - ans;
return ans;
};
dfs1(1, -1);
vector<vector<int>> sub(n * 4 + 1);
auto etour_cmp = [&] (int u, int v) { return pw[u] < pw[v]; };
function<int(int, int, int)> build = [&] (int l, int r, int k) {
vector<int>& sorted = sub[k];
if (r - l > 1) {
int m = l + (r - l) / 2;
vector<int>&lsorted = sub[build(l, m, k * 2)];
vector<int>&rsorted = sub[build(m, r, k * 2 + 1)];
merge(
lsorted.begin(), lsorted.end(),
rsorted.begin(), rsorted.end(),
back_inserter(sorted), etour_cmp
);
} else {
sorted.insert(sorted.end(), etour.begin()+l, etour.begin()+r);
}
return k;
};
int k = build(0, etour.size(), 1);
int64_t ans = 2 * tw; // worst case - triplicate the tree
function<int(vector<int>&,int)> find_closest_helper = [&] (vector<int>& arr, int64_t hw) {
int l = 0, r = arr.size();
int64_t best = -1;
int best_idx;
while (l < r) {
int m = l + (r - l) / 2;
if (best == -1 || std::abs(2 * pw[arr[m]] - hw) < best) {
best = std::abs(2 * pw[arr[m]] - hw);
best_idx = m;
}
if (2 * pw[arr[m]] < hw)
l = m + 1;
else
r = m;
}
return arr[best_idx];
};
function<int(int, int, int64_t, int, int, int)> find_closest = [&] (int l, int r, int64_t hw, int tl, int tr, int tk) {
l = max(l, tl);
r = min(r, tr);
if (l >= r) {
return -1;
}
if (l == tl && r == tr) {
return find_closest_helper(sub[tk], hw);
}
int tm = tl + (tr - tl) / 2;
int lans = find_closest(l, r, hw, tl, tm, tk * 2);
int rans = find_closest(l, r, hw, tm, tr, tk * 2 + 1);
if (lans == -1) return rans;
if (rans == -1) return lans;
if (std::abs(2 * pw[lans] - hw) < std::abs(2 * pw[rans] - hw))
return lans;
return rans;
};
for (int u = 1; u <= n; ++u) {
// we cut away node u and obtain a tree of weight a and its parent is (tw - a)
int64_t a = tw - pw[u];
// now we need to find vertex v such that
// max(pw[v] - a, tw - pw[v]) is minimal
// a <= pw[v] <= tw
// so we need to find v s.t. 2 * pw[v] is closest to (a + tw)
pair<int, int> atime = etime[u];
// we ignore all vertices in u subtree
int v1 = find_closest(0, atime.first, a + tw, 0, etour.size(), 1);
int v2 = find_closest(atime.second, etour.size(), a + tw, 0, etour.size(), 1);
auto evaluate = [&] (int v) -> int64_t {
int64_t b = pw[v] - a;
int64_t c = tw - a - b;
return 3 * max(a, max(b, c)) - a - b - c;
};
for (auto v : vector<int>{v1, v2}) {
if (v == -1) continue;
ans = min(ans, evaluate(v));
}
}
cout << ans << endl;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgppbnQgbWFpbigpIHsKCXN0ZDo6aW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSk7CglpbnQgbjsgY2luID4+IG47Cgl2ZWN0b3I8aW50NjRfdD4gdyhuKzEpOwoJaW50NjRfdCB0dyA9IDA7Cglmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKCQljaW4gPj4gd1tpXTsgdHcgKz0gd1tpXTsKCX0KCXZlY3Rvcjx2ZWN0b3I8aW50Pj4gYWRqKG4rMSk7Cglmb3IgKGludCBpID0gMTsgaSA8PSBuIC0gMTsgKytpKSB7CgkJaW50IHUsIHY7IGNpbiA+PiB1ID4+IHY7IGFkalt1XS5wdXNoX2JhY2sodik7IGFkalt2XS5wdXNoX2JhY2sodSk7Cgl9Cgl2ZWN0b3I8aW50NjRfdD4gcHcobisxKTsKCXZlY3RvcjxwYWlyPGludCwgaW50Pj4gZXRpbWUobisxKTsKCXZlY3RvcjxpbnQ+IGV0b3VyOwoJZnVuY3Rpb248aW50NjRfdChpbnQsIGludCk+IGRmczEgPSBbJl0gKGludCB1LCBpbnQgZnJvbSkgewoJCWludCBlbnRlciA9IGV0b3VyLnNpemUoKTsKCQlldG91ci5wdXNoX2JhY2sodSk7CgkJaW50NjRfdCBhbnMgPSB3W3VdOwoJCWZvciAoYXV0byB2IDogYWRqW3VdKSBpZiAodiAhPSBmcm9tKSBhbnMgKz0gZGZzMSh2LCB1KTsKCQlpbnQgbGVmdCA9IGV0b3VyLnNpemUoKTsKCQlldGltZVt1XSA9IHtlbnRlciwgbGVmdH07CgkJcHdbdV0gPSB0dyAtIGFuczsKCQlyZXR1cm4gYW5zOwoJfTsKCWRmczEoMSwgLTEpOwoJdmVjdG9yPHZlY3RvcjxpbnQ+PiBzdWIobiAqIDQgKyAxKTsKCWF1dG8gZXRvdXJfY21wID0gWyZdIChpbnQgdSwgaW50IHYpIHsgcmV0dXJuIHB3W3VdIDwgcHdbdl07IH07CglmdW5jdGlvbjxpbnQoaW50LCBpbnQsIGludCk+IGJ1aWxkID0gWyZdIChpbnQgbCwgaW50IHIsIGludCBrKSB7CgkJdmVjdG9yPGludD4mIHNvcnRlZCA9IHN1YltrXTsKCQlpZiAociAtIGwgPiAxKSB7CgkJCWludCBtID0gbCArIChyIC0gbCkgLyAyOwoJCQl2ZWN0b3I8aW50PiZsc29ydGVkID0gc3ViW2J1aWxkKGwsIG0sIGsgKiAyKV07CgkJCXZlY3RvcjxpbnQ+JnJzb3J0ZWQgPSBzdWJbYnVpbGQobSwgciwgayAqIDIgKyAxKV07CgkJCW1lcmdlKAoJCQkJbHNvcnRlZC5iZWdpbigpLCBsc29ydGVkLmVuZCgpLAoJCQkJcnNvcnRlZC5iZWdpbigpLCByc29ydGVkLmVuZCgpLAoJCQkJYmFja19pbnNlcnRlcihzb3J0ZWQpLCBldG91cl9jbXAKCQkJKTsKCQl9IGVsc2UgewoJCQlzb3J0ZWQuaW5zZXJ0KHNvcnRlZC5lbmQoKSwgZXRvdXIuYmVnaW4oKStsLCBldG91ci5iZWdpbigpK3IpOwoJCX0KCQlyZXR1cm4gazsKCX07CglpbnQgayA9IGJ1aWxkKDAsIGV0b3VyLnNpemUoKSwgMSk7CglpbnQ2NF90IGFucyA9IDIgKiB0dzsgLy8gd29yc3QgY2FzZSAtIHRyaXBsaWNhdGUgdGhlIHRyZWUKCglmdW5jdGlvbjxpbnQodmVjdG9yPGludD4mLGludCk+IGZpbmRfY2xvc2VzdF9oZWxwZXIgPSBbJl0gKHZlY3RvcjxpbnQ+JiBhcnIsIGludDY0X3QgaHcpIHsKCQlpbnQgbCA9IDAsIHIgPSBhcnIuc2l6ZSgpOwoJCWludDY0X3QgYmVzdCA9IC0xOwoJCWludCBiZXN0X2lkeDsKCQl3aGlsZSAobCA8IHIpIHsKCQkJaW50IG0gPSBsICsgKHIgLSBsKSAvIDI7CgkJCWlmIChiZXN0ID09IC0xIHx8IHN0ZDo6YWJzKDIgKiBwd1thcnJbbV1dIC0gaHcpIDwgYmVzdCkgewoJCQkJYmVzdCA9IHN0ZDo6YWJzKDIgKiBwd1thcnJbbV1dIC0gaHcpOwoJCQkJYmVzdF9pZHggPSBtOwoJCQl9CgkJCWlmICgyICogcHdbYXJyW21dXSA8IGh3KQoJCQkJbCA9IG0gKyAxOwoJCQllbHNlCgkJCQlyID0gbTsKCQl9CgkJcmV0dXJuIGFycltiZXN0X2lkeF07Cgl9OwoKCWZ1bmN0aW9uPGludChpbnQsIGludCwgaW50NjRfdCwgaW50LCBpbnQsIGludCk+IGZpbmRfY2xvc2VzdCA9IFsmXSAoaW50IGwsIGludCByLCBpbnQ2NF90IGh3LCBpbnQgdGwsIGludCB0ciwgaW50IHRrKSB7CgkJbCA9IG1heChsLCB0bCk7CgkJciA9IG1pbihyLCB0cik7CgkJaWYgKGwgPj0gcikgewoJCQlyZXR1cm4gLTE7CgkJfQoJCWlmIChsID09IHRsICYmIHIgPT0gdHIpIHsKCQkJcmV0dXJuIGZpbmRfY2xvc2VzdF9oZWxwZXIoc3ViW3RrXSwgaHcpOwoJCX0KCQlpbnQgdG0gPSB0bCArICh0ciAtIHRsKSAvIDI7CgkJaW50IGxhbnMgPSBmaW5kX2Nsb3Nlc3QobCwgciwgaHcsIHRsLCB0bSwgdGsgKiAyKTsKCQlpbnQgcmFucyA9IGZpbmRfY2xvc2VzdChsLCByLCBodywgdG0sIHRyLCB0ayAqIDIgKyAxKTsKCQlpZiAobGFucyA9PSAtMSkgcmV0dXJuIHJhbnM7CgkJaWYgKHJhbnMgPT0gLTEpIHJldHVybiBsYW5zOwoJCWlmIChzdGQ6OmFicygyICogcHdbbGFuc10gLSBodykgPCBzdGQ6OmFicygyICogcHdbcmFuc10gLSBodykpCgkJCXJldHVybiBsYW5zOwoJCXJldHVybiByYW5zOwoJfTsKCglmb3IgKGludCB1ID0gMTsgdSA8PSBuOyArK3UpIHsKCQkvLyB3ZSBjdXQgYXdheSBub2RlIHUgYW5kIG9idGFpbiBhIHRyZWUgb2Ygd2VpZ2h0IGEgYW5kIGl0cyBwYXJlbnQgaXMgKHR3IC0gYSkKCQlpbnQ2NF90IGEgPSB0dyAtIHB3W3VdOwoKCQkvLyBub3cgd2UgbmVlZCB0byBmaW5kIHZlcnRleCB2IHN1Y2ggdGhhdAoJCS8vIG1heChwd1t2XSAtIGEsIHR3IC0gcHdbdl0pIGlzIG1pbmltYWwKCQkvLyBhIDw9IHB3W3ZdIDw9IHR3CgkJLy8gc28gd2UgbmVlZCB0byBmaW5kIHYgcy50LiAyICogcHdbdl0gaXMgY2xvc2VzdCB0byAoYSArIHR3KQoKCQlwYWlyPGludCwgaW50PiBhdGltZSA9IGV0aW1lW3VdOwoKCQkvLyB3ZSBpZ25vcmUgYWxsIHZlcnRpY2VzIGluIHUgc3VidHJlZQoJCWludCB2MSA9IGZpbmRfY2xvc2VzdCgwLCBhdGltZS5maXJzdCwgYSArIHR3LCAwLCBldG91ci5zaXplKCksIDEpOwoJCWludCB2MiA9IGZpbmRfY2xvc2VzdChhdGltZS5zZWNvbmQsIGV0b3VyLnNpemUoKSwgYSArIHR3LCAwLCBldG91ci5zaXplKCksIDEpOwoKCQlhdXRvIGV2YWx1YXRlID0gWyZdIChpbnQgdikgLT4gaW50NjRfdCB7CgkJCWludDY0X3QgYiA9IHB3W3ZdIC0gYTsKCQkJaW50NjRfdCBjID0gdHcgLSBhIC0gYjsKCQkJcmV0dXJuIDMgKiBtYXgoYSwgbWF4KGIsIGMpKSAtIGEgLSBiIC0gYzsKCQl9OwoKCQlmb3IgKGF1dG8gdiA6IHZlY3RvcjxpbnQ+e3YxLCB2Mn0pIHsKCQkJaWYgKHYgPT0gLTEpIGNvbnRpbnVlOwoJCQlhbnMgPSBtaW4oYW5zLCBldmFsdWF0ZSh2KSk7CgkJfQoJfQoKCWNvdXQgPDwgYW5zIDw8IGVuZGw7Cn0K