#include <bits/stdc++.h>
using namespace std;
int n, size[150005], h[150005], cnt, root, minn, tot = 0, maxd;
bool vis[150005];
long long ans = 0;
long long a[150005];
struct T {
  struct Tree {
    long long a, b;
  } tree[600005];
  void Build(int k, int l, int r) {
    tree[k].a = 0;
    tree[k].b = 0;
    if (l == r) return;
    int mid = (l + r) >> 1;
    Build(k << 1, l, mid);
    Build(k << 1 | 1, mid + 1, r);
  }
  void update(int k, int l, int r, long long a, long long b) {
    if (tree[k].a * l + tree[k].b <= a * l + b &&
        tree[k].a * r + tree[k].b <= a * r + b) {
      tree[k].a = a;
      tree[k].b = b;
      return;
    }
    if (tree[k].a * l + tree[k].b >= a * l + b &&
        tree[k].a * r + tree[k].b >= a * r + b)
      return;
    int mid = (l + r) >> 1;
    if (tree[k].a * mid + tree[k].b < a * mid + b)
      swap(tree[k].a, a), swap(tree[k].b, b);
    if (l == r) return;
    if (a < tree[k].a)
      update(k << 1, l, mid, a, b);
    else
      update(k << 1 | 1, mid + 1, r, a, b);
  }
  long long ask(int k, int l, int r, long long x, long long v) {
    long long s = tree[k].a * x + tree[k].b + v;
    if (l == r) return s;
    int mid = (l + r) >> 1;
    if (x <= mid)
      s = max(s, ask(k << 1, l, mid, x, v));
    else
      s = max(s, ask(k << 1 | 1, mid + 1, r, x, v));
    return s;
  }
} T;
struct que {
  long long a, b, a2, b2;
  int bel, l;
} s[150005];
bool cmp(que a, que b) { return a.bel < b.bel; }
struct Edge {
  int to, next;
} w[300005];
void add(int x, int y) {
  w[++cnt] = (Edge){y, h[x]};
  h[x] = cnt;
}
void findroot(int x, int fa, int num) {
  size[x] = 1;
  int s = 0;
  for (int i = h[x]; i; i = w[i].next) {
    int to = w[i].to;
    if (to == fa || vis[to]) continue;
    findroot(to, x, num);
    size[x] += size[to];
    s = max(s, size[to]);
  }
  s = max(s, num - size[x]);
  if (s < minn) minn = s, root = x;
}
void dfs2(int x, int fa) {
  size[x] = 1;
  for (int i = h[x]; i; i = w[i].next) {
    int to = w[i].to;
    if (to == fa || vis[to]) continue;
    dfs2(to, x);
    size[x] += size[to];
  }
}
void dfs(int x, int fa, int xx, int l, long long a1, long long b1, long long a2,
         long long b2) {
  maxd = max(maxd, l + 1);
  bool flag = 1;
  for (int i = h[x]; i; i = w[i].next) {
    int to = w[i].to;
    if (to == fa || vis[to]) continue;
    flag = 0;
    dfs(to, x, xx, l + 1, a1 + a[to], b1 + a1 + a[to], a2 + a[to],
        b2 + a[to] * (l + 1));
  }
  if (flag) s[++tot] = (que){a1, b1, a2, b2, xx, l};
}
void Solve(int x) {
  vis[x] = 1;
  maxd = 1;
  tot = 0;
  dfs2(x, 0);
  for (int i = h[x]; i; i = w[i].next) {
    int to = w[i].to;
    if (vis[to]) continue;
    dfs(to, x, to, 1, a[x] + a[to], 2 * a[x] + a[to], a[to], a[to]);
  }
  sort(s + 1, s + tot + 1, cmp);
  T.Build(1, 1, maxd);
  int j = 1;
  for (int i = 1; i <= tot; i++)
    ans = max(ans, max(s[i].b, s[i].b2 + s[i].a2 + a[x]));
  for (int i = 1; i <= tot;) {
    j = i;
    while (j <= tot && s[j].bel == s[i].bel)
      ans = max(ans, T.ask(1, 1, maxd, s[j].l + 1, s[j].b)), j++;
    while (i < j) T.update(1, 1, maxd, s[i].a2, s[i].b2), i++;
  }
  T.Build(1, 1, maxd);
  for (int i = tot; i >= 1;) {
    j = i;
    while (j >= 1 && s[j].bel == s[i].bel)
      ans = max(ans, T.ask(1, 1, maxd, s[j].l + 1, s[j].b)), j--;
    while (i > j) T.update(1, 1, maxd, s[i].a2, s[i].b2), i--;
  }
  for (int i = h[x]; i; i = w[i].next) {
    int to = w[i].to;
    if (vis[to]) continue;
    minn = 0x3f3f3f3f;
    findroot(to, x, size[to]);
    Solve(root);
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    add(x, y), add(y, x);
  }
  for (int i = 1; i <= n; i++) scanf("%lld", &a[i]), ans = max(ans, a[i]);
  root = 0, minn = 0x3f3f3f3f;
  findroot(1, 0, n);
  Solve(root);
  printf("%lld\n", ans);
}
