#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 50;
struct LiChao_segment_tree {
  inline long long f(long long k, int x, long long b) { return k * x + b; }
  long long k[MAXN << 2], b[MAXN << 2];
  int lz[MAXN << 2];
  int N;
  void init(int n) {
    N = n;
    lz[1] = 1;
    k[1] = b[1] = 0;
  }
  inline void down(int rt) {
    if (!lz[rt]) return;
    lz[rt << 1] = lz[rt << 1 | 1] = 1;
    k[rt << 1] = k[rt << 1 | 1] = b[rt << 1] = b[rt << 1 | 1] = 0;
    lz[rt] = 0;
    return;
  }
  void update(int rt, int l, int r, long long ck, long long cb) {
    if (f(ck, ((l + r) >> 1), cb) > f(k[rt], ((l + r) >> 1), b[rt]))
      swap(k[rt], ck), swap(b[rt], cb);
    if (l == r) return;
    down(rt);
    if (ck > k[rt])
      update(rt << 1 | 1, ((l + r) >> 1) + 1, r, ck, cb);
    else
      update(rt << 1, l, ((l + r) >> 1), ck, cb);
  }
  long long qry(int rt, int l, int r, int x) {
    long long ans = f(k[rt], x, b[rt]);
    if (l == r) return ans;
    down(rt);
    if (x <= ((l + r) >> 1))
      ans = max(ans, qry(rt << 1, l, ((l + r) >> 1), x));
    else
      ans = max(ans, qry(rt << 1 | 1, ((l + r) >> 1) + 1, r, x));
    return ans;
  }
} T;
vector<int> g[MAXN];
int sz[MAXN], Max_Son[MAXN], vis[MAXN], totsz;
long long a[MAXN];
int n, rt;
long long ans = 0;
void get_rt(int u, int fa) {
  sz[u] = 1;
  Max_Son[u] = 0;
  for (int v : g[u]) {
    if (v == fa || vis[v]) continue;
    get_rt(v, u);
    sz[u] += sz[v];
    Max_Son[u] = max(Max_Son[u], sz[v]);
  }
  Max_Son[u] = max(Max_Son[u], totsz - sz[u]);
  if (Max_Son[rt] > Max_Son[u]) rt = u;
}
void init() {
  scanf("%d", &n);
  for (int i = 1; i < n; ++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("%I64d", &a[i]);
  totsz = n;
}
void qry(int u, int fa, long long sum, long long xsum, int d) {
  int f = 0;
  d++;
  sum += a[u];
  xsum += sum;
  for (int v : g[u]) {
    if (vis[v] || v == fa) continue;
    f = 1;
    qry(v, u, sum, xsum, d);
  }
  if (f) return;
  ans = max(ans, xsum + T.qry(1, 1, T.N, d));
}
void update(int u, int fa, long long sum, long long xsum, int d) {
  d++;
  sum += a[u];
  xsum += d * a[u];
  int f = 0;
  for (int v : g[u]) {
    if (vis[v] || v == fa) continue;
    f = 1;
    update(v, u, sum, xsum, d);
  }
  if (f) return;
  T.update(1, 1, T.N, sum, xsum);
}
void cal(int u, int cursize) {
  T.init(cursize);
  for (int i = 0; i < g[u].size(); ++i) {
    int v = g[u][i];
    if (vis[v]) continue;
    qry(v, u, a[u], a[u], 1);
    update(v, u, 0, 0, 0);
  }
  ans = max(ans, a[u] + T.qry(1, 1, T.N, 1));
  T.init(cursize);
  for (int i = g[u].size() - 1; i >= 0; --i) {
    int v = g[u][i];
    if (vis[v]) continue;
    qry(v, u, a[u], a[u], 1);
    update(v, u, 0, 0, 0);
  }
}
void Dfs(int u, int cursize) {
  vis[u] = 1;
  cal(u, cursize);
  for (int v : g[u]) {
    if (vis[v]) continue;
    totsz = sz[v] < sz[u] ? sz[v] : cursize - sz[u];
    rt = 0;
    get_rt(v, 0);
    Dfs(rt, totsz);
  }
}
void sol() {
  rt = 0;
  Max_Son[rt] = n + 1;
  get_rt(1, 0);
  Dfs(rt, n);
  cout << ans << endl;
}
int main() {
  init();
  sol();
}
