#include <bits/stdc++.h>
using namespace std;
const int MAXN = 150005;
template <typename T>
inline void read(T &AKNOI) {
  T x = 0, flag = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') flag = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  AKNOI = flag * x;
}
template <typename T>
inline void cmax(T &x, T y) {
  if (x < y) x = y;
}
int n;
long long a[MAXN], ans;
int vis[MAXN], siz[MAXN], son[MAXN], tsiz, root;
vector<int> e[MAXN];
struct SegmentTree {
  int tot, key[MAXN << 2], cln[MAXN << 2];
  long long k[MAXN], b[MAXN];
  inline long long F(int i, int x) { return k[i] * x + b[i]; }
  inline void putcln(int rt) {
    cln[rt] = 1;
    key[rt] = 0;
  }
  inline void pushdown(int rt) {
    if (cln[rt]) {
      putcln((rt << 1));
      putcln((rt << 1) | 1);
      cln[rt] = 0;
    }
  }
  void Update(int rt, int b, int e, int i) {
    int mid = (b + e) >> 1;
    if (F(key[rt], mid) < F(i, mid)) swap(key[rt], i);
    if (b == e) return;
    pushdown(rt);
    if (k[i] < k[key[rt]])
      Update((rt << 1), b, mid, i);
    else
      Update((rt << 1) | 1, mid + 1, e, i);
  }
  long long Query(int rt, int b, int e, int p) {
    long long ret = F(key[rt], p);
    if (b == e) return ret;
    int mid = (b + e) >> 1;
    pushdown(rt);
    if (p <= mid)
      cmax(ret, Query((rt << 1), b, mid, p));
    else
      cmax(ret, Query((rt << 1) | 1, mid + 1, e, p));
    return ret;
  }
  void clean() {
    putcln(1);
    tot = 0;
  }
  void update(long long _k, long long _b) {
    k[++tot] = _k;
    b[tot] = _b;
    Update(1, 1, n, tot);
  }
  long long query(int p) { return Query(1, 1, n, p); }
} seg;
void GetRoot(int u, int fa) {
  siz[u] = 1;
  son[u] = 0;
  for (auto v : e[u]) {
    if (v == fa || vis[v]) continue;
    GetRoot(v, u);
    cmax(son[u], siz[v]);
    siz[u] += siz[v];
  }
  cmax(son[u], tsiz - siz[u]);
  if (son[u] < son[root]) root = u;
}
void GetVal(int u, int fa, long long as, long long ss, int dep) {
  as += a[u];
  ss += a[u] * dep;
  bool leaf = 1;
  for (auto v : e[u]) {
    if (v == fa || vis[v]) continue;
    leaf = 0;
    GetVal(v, u, as, ss, dep + 1);
  }
  if (leaf) {
    cmax(ans, a[root] + as + ss);
    seg.update(as, ss);
  }
}
void GetAns(int u, int fa, long long as, long long ss, int dep) {
  as += a[u];
  ss += as;
  bool leaf = 1;
  for (auto v : e[u]) {
    if (v == fa || vis[v]) continue;
    leaf = 0;
    GetAns(v, u, as, ss, dep + 1);
  }
  if (leaf) {
    cmax(ans, ss + seg.query(dep));
  }
}
void PointDC(int u) {
  vis[u] = 1;
  int sz = e[u].size();
  seg.clean();
  for (int i = 0; i < sz; ++i) {
    int v = e[u][i];
    if (vis[v]) continue;
    GetAns(v, u, a[u], a[u], 2);
    GetVal(v, u, 0, 0, 1);
  }
  seg.clean();
  for (int i = sz - 1; i >= 0; --i) {
    int v = e[u][i];
    if (vis[v]) continue;
    GetAns(v, u, a[u], a[u], 2);
    GetVal(v, u, 0, 0, 1);
  }
  for (auto v : e[u]) {
    if (vis[v]) continue;
    tsiz = siz[v];
    root = 0;
    GetRoot(v, u);
    PointDC(root);
  }
}
void init() {
  read(n);
  for (int i = 1, u, v; i < n; ++i) {
    read(u);
    read(v);
    e[u].push_back(v);
    e[v].push_back(u);
  }
  for (int i = 1; i <= n; ++i) {
    read(a[i]);
  }
}
void solve() {
  tsiz = son[0] = n;
  root = 0;
  GetRoot(1, 0);
  PointDC(root);
  printf("%lld\n", ans);
}
int main() {
  init();
  solve();
  return 0;
}
