#include <bits/stdc++.h>
using namespace std;
inline int read() {
  register int x = 0, f = 1;
  register char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = 0;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + (ch ^ '0');
    ch = getchar();
  }
  return f ? x : -x;
}
const int N = 1.5e5 + 5;
int n, w[N];
long long ans;
vector<int> E[N];
namespace LichaoTree {
long long k[N << 2], b[N << 2];
bool flg[N << 2];
inline long long cal(long long k, long long b, long long x) {
  return k * x + b;
}
void build(int p, int l, int r) {
  k[p] = b[p] = flg[p] = 0;
  if (l == r) return;
  int mid = (l + r) >> 1;
  build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
}
void insert(int p, int l, int r, long long _k, long long _b) {
  if (!flg[p]) return k[p] = _k, b[p] = _b, flg[p] = 1, void();
  long long l1 = cal(k[p], b[p], l), r1 = cal(k[p], b[p], r),
            l2 = cal(_k, _b, l), r2 = cal(_k, _b, r);
  if (l1 <= l2 && r1 <= r2) return k[p] = _k, b[p] = _b, void();
  if (l1 > l2 && r1 > r2) return;
  int mid = (l + r) >> 1;
  if (cal(k[p], b[p], mid) < cal(_k, _b, mid)) swap(k[p], _k), swap(b[p], _b);
  if (_k <= k[p])
    insert(p << 1, l, mid, _k, _b);
  else
    insert(p << 1 | 1, mid + 1, r, _k, _b);
}
long long query(int p, int l, int r, int x) {
  if (l == r) return cal(k[p], b[p], x);
  int mid = (l + r) >> 1;
  if (x <= mid)
    return max(cal(k[p], b[p], x), query(p << 1, l, mid, x));
  else
    return max(cal(k[p], b[p], x), query(p << 1 | 1, mid + 1, r, x));
}
}  // namespace LichaoTree
using namespace LichaoTree;
namespace Partition {
int rt, rtsiz, siz[N], vis[N], cnt;
struct node {
  int id;
  long long p1, p2, s, l;
  inline node(int _id = 0, long long _p1 = 0, long long _p2 = 0,
              long long _s = 0, long long _l = 0)
      : id(_id), p1(_p1), p2(_p2), s(_s), l(_l) {}
} a[N];
void getnode(int u, int pa, int id, int rt, long long p1, long long p2,
             long long s, long long l) {
  int flg = 0;
  s += w[u], l += 1, p1 += (l + 1) * w[u], p2 += s - w[rt];
  for (int v : E[u]) {
    if (v == pa || vis[v]) continue;
    flg = 1;
    getnode(v, u, id, rt, p1, p2, s, l);
  }
  if (!flg) a[++cnt] = node(id, p1, p2, s, l);
}
void work(int rt, int n) {
  a[cnt = 1] = node(rt, w[rt], 0, w[rt], 0);
  for (int v : E[rt]) {
    if (vis[v]) continue;
    getnode(v, 0, v, rt, w[rt], 0, w[rt], 0);
  }
  build(1, 1, n);
  for (int l = 1, r; l <= cnt; l = r + 1) {
    r = l;
    while (r < cnt && a[r + 1].id == a[l].id) ++r;
    for (int i = (l), _ed = (r); i <= _ed; ++i)
      ans = max(ans, query(1, 1, n, a[i].l) + a[i].p2);
    for (int i = (l), _ed = (r); i <= _ed; ++i)
      insert(1, 1, n, a[i].s, a[i].p1);
  }
  build(1, 1, n);
  for (int r = cnt, l; r; r = l - 1) {
    l = r;
    while (l > 1 && a[l - 1].id == a[r].id) --l;
    for (int i = (l), _ed = (r); i <= _ed; ++i)
      ans = max(ans, query(1, 1, n, a[i].l) + a[i].p2);
    for (int i = (l), _ed = (r); i <= _ed; ++i)
      insert(1, 1, n, a[i].s, a[i].p1);
  }
}
void getrt(int u, int pa, int sum) {
  siz[u] = 1;
  int mx = 0;
  for (int v : E[u]) {
    if (v == pa || vis[v]) continue;
    getrt(v, u, sum), siz[u] += siz[v];
    mx = max(mx, siz[v]);
  }
  mx = max(mx, sum - siz[u]);
  if (mx < rtsiz) rt = u, rtsiz = mx;
}
void solve(int u, int sum) {
  rt = 0, rtsiz = n + 1;
  getrt(u, 0, sum), vis[u = rt] = 1;
  work(u, sum);
  for (int v : E[u]) {
    if (vis[v]) continue;
    solve(v, siz[u] > siz[v] ? siz[v] : sum - siz[u]);
  }
}
}  // namespace Partition
int main() {
  n = read();
  for (int i = (1), _ed = (n - 1); i <= _ed; ++i) {
    int u = read(), v = read();
    E[u].push_back(v), E[v].push_back(u);
  }
  for (int i = (1), _ed = (n); i <= _ed; ++i) w[i] = read();
  Partition::solve(1, n);
  printf("%lld\n", ans);
  return 0;
}
