#include <bits/stdc++.h>
using namespace std;
const int maxn = (int)2e5 + 100;
const int mod = (int)1e9 + 7;
const int P = (int)1e6 + 7;
const double pi = acos(-1.0);
bool Q;
struct Line {
  mutable long long k, m, p;
  bool operator<(const Line& o) const { return Q ? p < o.p : k < o.k; }
};
struct LineContainer : multiset<Line> {
  const long long mod = LLONG_MAX;
  long long div(long long a, long long b) {
    return a / b - ((a ^ b) < 0 && a % b);
  }
  bool isect(iterator x, iterator y) {
    if (y == end()) {
      x->p = mod;
      return false;
    }
    if (x->k == y->k)
      x->p = x->m > y->m ? mod : -mod;
    else
      x->p = div(y->m - x->m, x->k - y->k);
    return x->p >= y->p;
  }
  void add(long long k, long long m) {
    auto z = insert({k, m, 0}), y = z++, x = y;
    while (isect(y, z)) z = erase(z);
    if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
    while ((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y));
  }
  long long query(long long x) {
    assert(!empty());
    Q = 1;
    auto l = *lower_bound({0, 0, x});
    Q = 0;
    return l.k * x + l.m;
  }
} cur;
int n, tot, sz[maxn], a[maxn];
vector<int> g[maxn];
long long ans;
bool bad[maxn];
void dfs1(int v, int par = 0) {
  sz[v] = 1;
  for (auto to : g[v])
    if (!bad[to] && to != par) dfs1(to, v), sz[v] += sz[to];
}
int Find(int v, int par = 0) {
  for (auto to : g[v])
    if (!bad[to] && to != par && sz[to] > tot / 2) return Find(to, v);
  return v;
}
void calc(int v, long long s1 = 0, long long s2 = 0, int par = 0, int lvl = 2) {
  ans = max(ans, s1 + cur.query(lvl));
  ans = max(ans, s1);
  for (auto to : g[v]) {
    if (!bad[to] && to != par) {
      calc(to, s1 + s2 + a[to], s2 + a[to], v, lvl + 1);
    }
  }
}
void add(int v, int par = 0, int lvl = 1, long long s1 = 0, long long s2 = 0) {
  s1 += lvl * 1ll * a[v];
  s2 += a[v];
  ans = max(ans, s1);
  cur.add(s2, s1);
  for (auto to : g[v]) {
    if (!bad[to] && to != par) {
      add(to, v, lvl + 1, s1, s2);
    }
  }
}
void build(int v) {
  dfs1(v);
  tot = sz[v];
  v = Find(v);
  bad[v] = 1;
  cur.clear();
  cur.add(0, 0);
  for (auto to : g[v]) {
    if (bad[to]) continue;
    calc(to, 2ll * a[v] + a[to], a[v] + a[to]);
    add(to);
  }
  cur.clear();
  cur.add(0, 0);
  reverse((g[v]).begin(), (g[v]).end());
  for (auto to : g[v]) {
    if (bad[to]) continue;
    calc(to, 2ll * a[v] + a[to], a[v] + a[to]);
    add(to);
  }
  for (auto to : g[v])
    if (!bad[to]) build(to);
}
void solve() {
  scanf("%d", &n);
  for (int i = (1); i <= (n - 1); ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u);
  }
  for (int i = (1); i <= (n); ++i) scanf("%d", &a[i]);
  build(1);
  printf("%lld\n", ans);
}
int main() {
  int t = 1;
  while (t--) solve();
}
