#include <bits/stdc++.h>   using namespace std;   template <typename T>   inline void chkmin(T &a, const T &b) {     a = a < b ? a : b;   }   template <typename T>   inline void chkmax(T &a, const T &b) {     a = a > b ? a : b;   }   const int MAXN = 150005, MAXT = 300005;   int sz[MAXN], val[MAXN], vis[MAXN], n, tot;   vector<int> gra[MAXN];   struct Tree {     long long k, b;     Tree *ls, *rs;     bool did;   } nd[MAXT], *rt;   vector<Tree *> cls;   long long ans;   Tree *build(int l, int r) {     Tree *cur = nd + (tot++);     cur->did = false;     if (l == r) return cur;     int mid = (l + r) >> 1;     cur->ls = build(l, mid);     cur->rs = build(mid + 1, r);     return cur;   }   void modify(long long k, long long b, int l = 1, int r = n, Tree *p = rt) {     if (p->did) {       long long f1 = p->k * l + p->b, f2 = p->k * r + p->b, g1 = k * l + b,                 g2 = k * r + b;       if (g1 >= f1 && g2 >= f2) {         p->k = k, p->b = b;         return;       } else if (g1 <= f1 && g2 <= f2)         return;       double in = 1.0 * (b - p->b) / (k - p->k);       int mid = (l + r) >> 1;       if (in <= mid) {         if (f1 >= g1 && f2 <= g2) {           modify(p->k, p->b, l, mid, p->ls);           p->k = k, p->b = b;         } else           modify(k, b, l, mid, p->ls);       } else {         if (f1 <= g1 && f2 >= g2) {           modify(p->k, p->b, mid + 1, r, p->rs);           p->k = k, p->b = b;         } else           modify(k, b, mid + 1, r, p->rs);       }     } else       p->k = k, p->b = b, p->did = true, cls.push_back(p);   }   long long query(int x, int l = 1, int r = n, Tree *p = rt) {     if (!p->did) return -1e18;     int mid = (l + r) >> 1;     long long res = p->k * x + p->b;     if (x <= mid)       chkmax(res, query(x, l, mid, p->ls));     else       chkmax(res, query(x, mid + 1, r, p->rs));     return res;   }   void get_sz(int u, int fa) {     sz[u] = 1;     for (int v : gra[u])       if (v != fa && !vis[v]) {         get_sz(v, u);         sz[u] += sz[v];       }   }   pair<int, int> get_rt(int u, int fa, int s) {     auto res = make_pair(MAXN, MAXN);     int mn = s;     for (int v : gra[u])       if (v != fa && !vis[v]) {         res = min(res, get_rt(v, u, s + sz[u] - sz[v]));         chkmax(mn, sz[v]);       }     return min(res, make_pair(mn, u));   }   void dfs1(int u, int fa, int dep, long long sum, long long cur, long long tmp) {     sum += val[u], cur += sum, ++dep, tmp += (long long)dep * val[u];     chkmax(ans, cur), chkmax(ans, tmp);     chkmax(ans, query(dep) + cur);     for (int v : gra[u])       if (v != fa && !vis[v]) dfs1(v, u, dep, sum, cur, tmp);   }   void dfs2(int u, int fa, int dep, long long sum, long long cur) {     ++dep, sum += val[u], cur += (long long)dep * val[u];     modify(sum, cur);     for (int v : gra[u])       if (v != fa && !vis[v]) dfs2(v, u, dep, sum, cur);   }   void divide(int u) {     get_sz(u, 0);     u = get_rt(u, 0, 0).second;     vis[u] = 1;     for (int v : gra[u])       if (!vis[v]) {         dfs1(v, u, 1, val[u], val[u], val[u]);         dfs2(v, u, 0, 0, 0);       }     for (Tree *p : cls) p->did = false;     cls.clear();     reverse(gra[u].begin(), gra[u].end());     for (int v : gra[u])       if (!vis[v]) {         dfs1(v, u, 1, val[u], val[u], val[u]);         dfs2(v, u, 0, 0, 0);       }     for (Tree *p : cls) p->did = false;     cls.clear();     for (int v : gra[u])       if (!vis[v]) divide(v);     vis[u] = 0;   }   int main() {     scanf( %d , &n);     rt = build(1, n);     for (int i = 1; i < n; i++) {       int u, v;       scanf( %d%d , &u, &v);       gra[u].push_back(v);       gra[v].push_back(u);     }     for (int i = 1; i <= n; i++) scanf( %d , val + i);     divide(1);     printf( %lld n , ans);     return 0;   }   