#include <bits/stdc++.h>   template <typename Tp>   inline void read(Tp &x) {     x = 0;     bool f = true;     char ch = getchar();     for (; ch <  0  || ch >  9 ; ch = getchar()) f ^= ch ==  - ;     for (; ch >=  0  && ch <=  9 ; ch = getchar()) x = x * 10 + (ch ^ 48);     x = f ? x : -x;   }   const int N = 15e4;   struct Node {     long long k, b;     bool exist;   };   struct Segment_Tree {     Node Tre[N * 4 + 5];     void build(int p, int l, int r) {       Tre[p].k = Tre[p].b = 0, Tre[p].exist = false;       if (l == r) return;       int mid = (l + r) >> 1;       build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);     }     void update(int p, int l, int r, long long k, long long b) {       if (!Tre[p].exist) {         Tre[p].exist = true;         Tre[p].k = k, Tre[p].b = b;         return;       }       long long l1 = k * l + b, r1 = k * r + b, l2 = Tre[p].k * l + Tre[p].b,                 r2 = Tre[p].k * r + Tre[p].b;       if (l1 <= l2 && r1 <= r2) return;       if (l1 >= l2 && r1 >= r2) {         Tre[p].k = k, Tre[p].b = b;         return;       }       double x = 1.0 * (b - Tre[p].b) / (Tre[p].k - k);       int mid = (l + r) >> 1;       if (l1 > l2) {         if (x <= mid)           update(p << 1, l, mid, k, b);         else {           update(p << 1 | 1, mid + 1, r, Tre[p].k, Tre[p].b);           Tre[p].k = k, Tre[p].b = b;         }       } else {         if (x <= mid) {           update(p << 1, l, mid, Tre[p].k, Tre[p].b);           Tre[p].k = k, Tre[p].b = b;         } else           update(p << 1 | 1, mid + 1, r, k, b);       }     }     long long query(int p, int l, int r, int x) {       if (l == r) return Tre[p].k * x + Tre[p].b;       int mid = (l + r) >> 1;       long long res = Tre[p].k * x + Tre[p].b;       if (x <= mid)         return std::max(res, query(p << 1, l, mid, x));       else         return std::max(res, query(p << 1 | 1, mid + 1, r, x));     }   };   Segment_Tree T;   int a[N + 5], siz[N + 5], rt, SZ, Max;   bool vis[N + 5];   long long ans;   std::vector<int> Vec[N + 5];   void find(int u, int ff) {     siz[u] = 1;     int mx = 0;     for (int i = 0; i < (int)Vec[u].size(); ++i) {       int v = Vec[u][i];       if (v == ff || vis[v]) continue;       find(v, u);       siz[u] += siz[v];       mx = std::max(mx, siz[v]);     }     mx = std::max(mx, SZ - siz[u]);     if (mx < Max) Max = mx, rt = u;   }   int m;   void dfs1(int u, int ff, int dep) {     m = std::max(m, dep);     for (int i = 0; i < (int)Vec[u].size(); ++i) {       int v = Vec[u][i];       if (vis[v] || v == ff) continue;       dfs1(v, u, dep + 1);     }   }   void dfs2(int u, int ff, long long sum, long long ssum, int dep) {     ssum += sum + a[u];     int cnt = 0;     for (int i = 0; i < (int)Vec[u].size(); ++i) {       int v = Vec[u][i];       if (v == ff || vis[v]) continue;       ++cnt;       dfs2(v, u, sum + a[u], ssum, dep + 1);     }     if (!cnt) ans = std::max(ans, ssum + T.query(1, 1, m, dep));   }   void dfs3(int u, int ff, long long sum, long long ssum, int dep) {     sum += a[u];     ssum += 1LL * dep * a[u];     int cnt = 0;     for (int i = 0; i < (int)Vec[u].size(); ++i) {       int v = Vec[u][i];       if (v == ff || vis[v]) continue;       ++cnt;       dfs3(v, u, sum, ssum, dep + 1);     }     if (!cnt) T.update(1, 1, m, sum, ssum);   }   inline void solve(int u) {     m = 0;     dfs1(u, 0, 1);     T.build(1, 1, m);     for (int i = 0; i < (int)Vec[u].size(); ++i) {       int v = Vec[u][i];       if (vis[v]) continue;       dfs2(v, u, a[u], a[u], 2);       dfs3(v, u, 0, 0, 1);     }     T.build(1, 1, m);     for (int i = (int)Vec[u].size() - 1; i >= 0; --i) {       int v = Vec[u][i];       if (vis[v]) continue;       dfs2(v, u, a[u], a[u], 2);       dfs3(v, u, 0, 0, 1);     }     ans = std::max(ans, a[u] + T.query(1, 1, m, 1));   }   void divide(int u) {     solve(u);     vis[u] = true;     for (int i = 0; i < (int)Vec[u].size(); ++i) {       int v = Vec[u][i];       if (vis[v]) continue;       SZ = Max = siz[v];       find(v, 0);       divide(rt);     }   }   int main() {     int n;     read(n);     for (int i = 1; i < n; ++i) {       int u, v;       read(u), read(v);       Vec[u].push_back(v), Vec[v].push_back(u);     }     for (int i = 1; i <= n; ++i) read(a[i]);     Max = SZ = n;     find(1, 0);     divide(rt);     printf( %lld n , ans);     return 0;   }