#include <bits/stdc++.h>
using namespace std;
const long long N = 150009;
long long head[N], cnt, n, p[N], siz[N], del[N], a[N], all, b[N], len[N],
    sum[N], _sum[N], Ans, Sum[N], bin[N], X;
struct Edge {
  long long nxt, to;
} g[N * 2];
struct LC_Tree {
  long long K[N], B[N], tag[N * 4], cnt;
  void Insert(long long a, long long b, long long fuck) {
    K[++cnt] = a, B[cnt] = b;
    Modify(1, 1, fuck, cnt);
  }
  long long val(long long id, long long x) { return K[id] * x + B[id]; }
  void Modify(long long k, long long l, long long r, long long id) {
    if (l == r) {
      tag[k] = val(id, l) > val(tag[k], l) ? id : tag[k];
      return;
    }
    long long mid = l + r >> 1;
    if (K[id] > K[tag[k]]) {
      if (val(id, mid) > val(tag[k], mid))
        Modify(k << 1, l, mid, tag[k]), tag[k] = id;
      else
        Modify(k << 1 | 1, mid + 1, r, id);
    } else {
      if (val(id, mid) > val(tag[k], mid))
        Modify(k << 1 | 1, mid + 1, r, tag[k]), tag[k] = id;
      else
        Modify(k << 1, l, mid, id);
    }
  }
  long long Query(long long k, long long l, long long r, long long x) {
    if (l == r) return val(tag[k], l);
    long long mid = l + r >> 1, res = val(tag[k], x);
    if (mid >= x)
      res = max(res, Query(k << 1, l, mid, x));
    else
      res = max(res, Query(k << 1 | 1, mid + 1, r, x));
    return res;
  }
  void clear(long long k, long long l, long long r) {
    tag[k] = 0;
    if (l == r) return;
    long long mid = l + r >> 1;
    clear(k << 1, l, mid);
    clear(k << 1 | 1, mid + 1, r);
  }
} T;
void add(long long from, long long to) {
  g[++cnt].nxt = head[from];
  g[cnt].to = to;
  head[from] = cnt;
}
void init() {
  scanf("%lld", &n);
  for (long long i = 1, x, y; i < n; i++)
    scanf("%lld %lld", &x, &y), add(x, y), add(y, x);
  for (long long i = 1; i <= n; i++) scanf("%lld", &p[i]);
}
void dfs(long long x, long long fa) {
  siz[x] = 1;
  for (long long i = head[x]; i; i = g[i].nxt) {
    long long v = g[i].to;
    if (v == fa || del[v]) continue;
    dfs(v, x);
    siz[x] += siz[v];
  }
}
long long Get_Weight(long long x) {
  dfs(x, -1);
  long long fa = -1, k = siz[x] / 2;
  while (1) {
    long long tmp = 0;
    for (long long i = head[x]; i; i = g[i].nxt) {
      long long v = g[i].to;
      if (v == fa || del[v]) continue;
      if (siz[tmp] < siz[v]) tmp = v;
    }
    if (siz[tmp] <= k) return x;
    fa = x, x = tmp;
  }
}
void dfs_1(long long x, long long fa, long long pre) {
  len[x] = len[fa] + 1, sum[x] = sum[fa] + p[x],
  _sum[x] = _sum[fa] + pre + p[x], Sum[x] = Sum[fa] + p[x] * (len[x] - 1);
  Ans = max(Ans, Sum[x] + sum[x] + p[X]);
  for (long long i = head[x]; i; i = g[i].nxt) {
    long long v = g[i].to;
    if (v == fa || del[v]) continue;
    dfs_1(v, x, pre + p[x]);
  }
}
void dfs_2(long long x, long long fa, long long fuck) {
  bin[++all] = x;
  Ans = max(Ans, T.Query(1, 1, fuck, len[x]) + _sum[x]);
  for (long long i = head[x]; i; i = g[i].nxt) {
    long long v = g[i].to;
    if (v == fa || del[v]) continue;
    dfs_2(v, x, fuck);
  }
}
void Get_Ans(long long x, long long fuck) {
  X = x;
  long long CNT = 0;
  T.cnt = sum[x] = Sum[x] = 0, len[x] = 1, _sum[x] = p[x], T.clear(1, 1, fuck);
  for (long long i = head[x]; i; i = g[i].nxt) {
    long long v = g[i].to;
    if (del[v]) continue;
    b[++CNT] = v;
    dfs_1(v, x, p[x]);
  }
  for (long long i = 1; i <= CNT; i++) {
    all = 0;
    dfs_2(b[i], x, fuck);
    for (long long j = 1; j <= all; j++)
      T.Insert(sum[bin[j]], Sum[bin[j]], fuck);
  }
  T.cnt = 0;
  T.clear(1, 1, fuck);
  for (long long i = CNT; i >= 1; i--) {
    all = 0;
    dfs_2(b[i], x, fuck);
    for (long long j = 1; j <= all; j++)
      T.Insert(sum[bin[j]], Sum[bin[j]], fuck);
  }
}
void conquer(long long x) {
  long long w = Get_Weight(x);
  del[w] = 1;
  Get_Ans(w, siz[x]);
  for (long long i = head[w]; i; i = g[i].nxt) {
    long long v = g[i].to;
    if (del[v]) continue;
    conquer(v);
  }
}
void work() {
  conquer(1);
  printf("%lld\n", Ans);
}
signed main() {
  init();
  work();
  return 0;
}
