#include <bits/stdc++.h>
using namespace std;
void Freopen() {
  freopen(
      "title"
      ".in",
      "r", stdin);
  freopen(
      "title"
      ".out",
      "w", stdout);
}
int read() {
  int g = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || '9' < ch) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while ('0' <= ch && ch <= '9') {
    g = g * 10 + ch - '0';
    ch = getchar();
  }
  return g * f;
}
const int N = 150005;
const int INF = 1e9;
int n, a[N], size[N], maxd, maxn, rt, vis[N];
long long ans;
vector<int> G[N];
struct node {
  long long k, b;
};
struct Seg {
  node t[N << 2];
  long long data(node a, int pos) { return a.k * pos + a.b; }
  void build(int v, int l, int r) {
    t[v] = node{0, 0};
    if (l == r) return void();
    int mid = l + r >> 1;
    build(v << 1, l, mid), build(v << 1 | 1, mid + 1, r);
  }
  void insert(int v, int l, int r, node now) {
    if (data(now, l) >= data(t[v], l) && data(now, r) >= data(t[v], r))
      return t[v] = now, void();
    if (data(now, l) <= data(t[v], l) && data(now, r) <= data(t[v], r))
      return void();
    int mid = l + r >> 1;
    if (data(now, mid) > data(t[v], mid)) swap(t[v], now);
    if (now.k < t[v].k)
      insert(v << 1, l, mid, now);
    else
      insert(v << 1 | 1, mid + 1, r, now);
  }
  long long query(int v, int l, int r, int pos) {
    long long ans = data(t[v], pos);
    if (l == r) return ans;
    int mid = l + r >> 1;
    if (pos <= mid)
      ans = max(ans, query(v << 1, l, mid, pos));
    else
      ans = max(ans, query(v << 1 | 1, mid + 1, r, pos));
    return ans;
  }
} seg;
void find(int x, int fa, int siz) {
  size[x] = 1;
  int mx = 0;
  for (auto y : G[x])
    if (y ^ fa)
      if (!vis[y]) {
        find(y, x, siz);
        size[x] += size[y];
        mx = max(mx, size[y]);
      }
  mx = max(mx, siz - size[x]);
  if (mx < maxn) maxn = mx, rt = x;
}
void get(int x, int fa, int dep) {
  size[x] = 1;
  maxd = max(maxd, dep);
  for (auto y : G[x])
    if (y ^ fa)
      if (!vis[y]) get(y, x, dep + 1), size[x] += size[y];
}
void get_ans(int x, int fa, int dep, long long su, long long all) {
  all += a[x], su += all;
  ans = max(ans, seg.query(1, 1, maxd, dep) + su);
  for (auto y : G[x])
    if (y ^ fa)
      if (!vis[y]) get_ans(y, x, dep + 1, su, all);
}
void ins_ans(int x, int fa, int dep, long long su, long long all) {
  all += a[x];
  su += 1ll * dep * a[x];
  seg.insert(1, 1, maxd, node{all, su});
  ans = max(ans, su);
  for (auto y : G[x])
    if (y ^ fa)
      if (!vis[y]) ins_ans(y, x, dep + 1, su, all);
}
void calc(int x) {
  seg.build(1, 1, maxd);
  seg.insert(1, 1, maxd, node{a[x], a[x]});
  for (auto y : G[x])
    if (!vis[y]) {
      get_ans(y, x, 1, 0, 0);
      ins_ans(y, x, 2, a[x], a[x]);
    }
  seg.build(1, 1, maxd);
  seg.insert(1, 1, maxd, node{a[x], a[x]});
  for (int i = (G[x].size() - 1); i >= (0); i--) {
    int y = G[x][i];
    if (!vis[y]) {
      get_ans(y, x, 1, 0, 0);
      ins_ans(y, x, 2, a[x], a[x]);
    }
  }
}
void solve(int x, int siz) {
  maxn = INF;
  rt = 0;
  find(x, 0, siz);
  x = rt;
  maxd = 0;
  get(x, 0, 1);
  calc(x);
  vis[x] = 1;
  for (auto y : G[x])
    if (!vis[y]) solve(y, size[y]);
}
signed main() {
  n = read();
  for (int i = (1); i <= (n - 1); i++) {
    int x = read(), y = read();
    G[x].push_back(y), G[y].push_back(x);
  }
  for (int i = (1); i <= (n); i++) a[i] = read();
  solve(1, n);
  return cout << ans, signed();
}
