#include <bits/stdc++.h>
using namespace std;
const int N = 150010;
int n, sum, root, tot, top, head[N], maxi[N], siz[N], dep[N];
long long a[N], ans;
bool v[N];
struct Edge {
  int ver, suiv;
} e[N << 1];
struct Node {
  long long fro, ed, v1, v2, sum, l;
} stk[N];
inline void lnk(int x, int y) {
  e[++tot].ver = y;
  e[tot].suiv = head[x];
  head[x] = tot;
}
struct SegmentTree {
  long long k, b;
} t[N << 2];
inline long long f(long long k, long long b, long long x) { return x * k + b; }
inline void insert(int p, int l, int r, long long x, long long y) {
  int mid = l + r >> 1;
  if (f(t[p].k, t[p].b, l) <= f(x, y, l) && f(t[p].k, t[p].b, r) <= f(x, y, r))
    return t[p].k = x, t[p].b = y, void();
  if (f(t[p].k, t[p].b, l) >= f(x, y, l) && f(t[p].k, t[p].b, r) >= f(x, y, r))
    return;
  if (f(t[p].k, t[p].b, mid) < f(x, y, mid)) swap(t[p].k, x), swap(t[p].b, y);
  if (f(t[p].k, t[p].b, l) < f(x, y, l))
    insert(p << 1, l, mid, x, y);
  else
    insert(p << 1 | 1, mid + 1, r, x, y);
}
inline long long query(int p, int l, int r, int x) {
  long long res = f(t[p].k, t[p].b, x), mid = l + r >> 1;
  if (l == r) return res;
  if (x <= mid) res = max(res, query(p << 1, l, mid, x));
  if (x > mid) res = max(res, query(p << 1 | 1, mid + 1, r, x));
  return res;
}
inline void clear(int p, int l, int r) {
  t[p].k = t[p].b = 0;
  if (l == r) return;
  int mid = l + r >> 1;
  clear(p << 1, l, mid);
  clear(p << 1 | 1, mid + 1, r);
}
inline void getroot(int x, int fa) {
  siz[x] = 1, maxi[x] = 0;
  for (int i = head[x]; i; i = e[i].suiv) {
    int y = e[i].ver;
    if (y == fa || v[y]) continue;
    getroot(y, x), siz[x] += siz[y];
    maxi[x] = max(maxi[x], siz[y]);
  }
  maxi[x] = max(maxi[x], sum - siz[x]);
  if (maxi[x] < maxi[root]) root = x;
}
int maxidep;
inline void getdis(int x, int fa, int fro, long long val1, long long val2,
                   long long sum) {
  if (x != root && !fro) fro = x;
  siz[x] = 1;
  maxidep = max(maxidep, dep[x] = dep[fa] + 1);
  bool isleaf = 1;
  for (int i = head[x]; i; i = e[i].suiv) {
    int y = e[i].ver;
    if (y == fa || v[y]) continue;
    isleaf = 0;
    getdis(y, x, fro, val1 + sum + a[y], val2 + a[y] * dep[x], sum + a[y]);
    siz[x] += siz[y];
  }
  if (isleaf) stk[++top] = (Node){fro, x, val1, val2, sum - a[root], dep[x]};
}
inline void solve(int x) {
  v[x] = 1;
  dep[x] = maxidep = top = 0;
  getdis(x, x, 0, a[x], 0, a[x]);
  stk[++top] = (Node){0, root, a[root], 0, 0, 1};
  stk[0].fro = stk[top + 1].fro = -1;
  for (int op = -1; op <= 1; op += 2) {
    clear(1, 1, maxidep);
    for (int i = op == 1 ? 1 : top, j; op == 1 ? i <= top : i;) {
      j = i;
      while (stk[j].fro == stk[i].fro)
        ans = max(ans, query(1, 1, maxidep, stk[j].l) + stk[j].v1), j += op;
      j = i;
      while (stk[j].fro == stk[i].fro)
        insert(1, 1, maxidep, stk[j].sum, stk[j].v2), j += op;
      i = j;
    }
  }
  for (int i = head[x]; i; i = e[i].suiv) {
    int y = e[i].ver;
    if (v[y] || siz[y] == 1) continue;
    sum = siz[y], root = 0;
    getroot(y, x);
    solve(root);
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1, x, y; i < n; i++) scanf("%d%d", &x, &y), lnk(x, y), lnk(y, x);
  for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
  maxi[root = 0] = sum = n;
  getroot(1, 1);
  solve(root);
  printf("%lld\n", ans);
  return 0;
}
