#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
const int inf = 1e9 + 10;
vector<int> v[maxn];
vector<int> vv;
int a[maxn];
int n;
int root, cnt, now;
int size[maxn];
int vis[maxn];
long long ans = 0;
struct node {
  long long cnt, sum, xsum;
  long long fsum;
  int ct;
} p[maxn];
pair<long long, long long> t[maxn << 2];
int la[maxn << 2];
void down(int now) {
  if (la[now] == 0) return;
  la[now] = 0;
  t[now].first = t[now].second = t[now * 2].first = t[now * 2].second =
      t[now * 2 + 1].first = t[now * 2 + 1].second = 0;
  la[now * 2] = la[now * 2 + 1] = 1;
}
void update(int now, int l, int r, long long k, long long b) {
  down(now);
  long long aa = 1LL * l * t[now].first + t[now].second,
            bb = 1LL * r * t[now].first + t[now].second;
  long long xx = 1LL * l * k + b, yy = 1LL * r * k + b;
  if (t[now].first == 0 && t[now].second == 0) {
    t[now].first = k;
    t[now].second = b;
    return;
  }
  if (xx >= aa && yy >= bb) {
    t[now].first = k, t[now].second = b;
    return;
  }
  if (xx <= aa && yy <= bb) return;
  long long m = (l + r) >> 1;
  long long om = 1LL * m * t[now].first + t[now].second, nm = 1LL * m * k + b;
  if (nm > om) {
    if (yy > bb)
      update(now * 2, l, m, t[now].first, t[now].second);
    else
      update(now * 2 + 1, m + 1, r, t[now].first, t[now].second);
    t[now].first = k, t[now].second = b;
  } else {
    if (yy > bb)
      update(now * 2 + 1, m + 1, r, k, b);
    else
      update(now * 2, l, m, k, b);
  }
}
long long quary(int now, int l, int r, int pos) {
  down(now);
  if (l == r) return 1LL * t[now].first * pos + t[now].second;
  int m = (l + r) >> 1;
  if (pos <= m)
    return max(1LL * t[now].first * pos + t[now].second,
               quary(now * 2, l, m, pos));
  else
    return max(1LL * t[now].first * pos + t[now].second,
               quary(now * 2 + 1, m + 1, r, pos));
}
void get(int x, int fa) {
  size[x] = 1;
  int ma = 0;
  for (int i : v[x]) {
    if (vis[i] || i == fa) continue;
    get(i, x);
    size[x] += size[i];
    ma = max(ma, size[i]);
  }
  ma = max(ma, now - size[x]);
  if (ma < cnt) cnt = ma, root = x;
}
void dis(int x, int fa) {
  p[x].ct = p[fa].ct + 1;
  p[x].cnt = p[fa].cnt + 1;
  p[x].sum = p[fa].sum + a[x];
  p[x].xsum = p[fa].xsum + 1LL * p[x].ct * a[x];
  p[x].fsum = p[fa].fsum + p[fa].sum + a[x];
  int f = 0;
  for (int i : v[x]) {
    if (vis[i] || i == fa) continue;
    dis(i, x);
    f = 1;
  }
  if (f == 0) vv.push_back(x);
}
void cal(int x) {
  p[x].cnt = 1;
  p[x].sum = p[x].xsum = p[x].fsum = a[x];
  p[x].ct = 1;
  int si = v[x].size();
  for (int k = 0; k < si; k++) {
    int i = v[x][k];
    if (vis[i]) continue;
    vv.clear();
    dis(i, x);
    for (int j : vv) ans = max(ans, quary(1, 1, n, p[j].cnt) + p[j].fsum);
    for (int j : vv) update(1, 1, n, p[j].sum - p[x].sum, p[j].xsum - p[j].sum);
  }
}
void cal2(int x) {
  p[x].cnt = 1;
  p[x].sum = p[x].xsum = p[x].fsum = a[x];
  p[x].ct = 1;
  int si = v[x].size();
  for (int k = si - 1; k >= 0; k--) {
    int i = v[x][k];
    if (vis[i]) continue;
    vv.clear();
    dis(i, x);
    for (int j : vv) ans = max(ans, quary(1, 1, n, p[j].cnt) + p[j].fsum);
    for (int j : vv) update(1, 1, n, p[j].sum - p[x].sum, p[j].xsum - p[j].sum);
  }
}
void solve(int x) {
  vis[x] = 1;
  la[1] = 1;
  down(1);
  cal(x);
  la[1] = 1;
  down(1);
  cal2(x);
  for (int i : v[x]) {
    if (vis[i]) continue;
    now = size[i], cnt = inf;
    get(i, 0);
    solve(root);
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1, x, y; i < n; i++) {
    scanf("%d%d", &x, &y);
    v[x].push_back(y);
    v[y].push_back(x);
  }
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  if (n == 2) {
    if (a[1] > a[2])
      printf("%d", a[1] * 2 + a[2]);
    else
      printf("%d", a[2] * 2 + a[1]);
    return 0;
  }
  now = n, cnt = inf;
  get(1, 0);
  solve(root);
  printf("%lld", ans);
  return 0;
}
