#include <bits/stdc++.h>
using namespace std;
struct Tree {
  struct Node {
    long long a, b;
  } tree[600005];
  void ins(int x, int l, int r, long long a, long long b) {
    if (l != r) {
      if (tree[x].a * l + tree[x].b <= a * l + b &&
          tree[x].a * r + tree[x].b <= a * r + b) {
        tree[x].a = a, tree[x].b = b;
        return;
      }
      if (tree[x].a * l + tree[x].b >= a * l + b &&
          tree[x].a * r + tree[x].b >= a * r + b)
        return;
      if (tree[x].a * ((l + r) >> 1) + tree[x].b < a * ((l + r) >> 1) + b)
        swap(tree[x].a, a), swap(tree[x].b, b);
      if (a < tree[x].a)
        ins(x << 1, l, ((l + r) >> 1), a, b);
      else
        ins(x << 1 | 1, ((l + r) >> 1) + 1, r, a, b);
    } else if (l * a + b > l * tree[x].a + tree[x].b) {
      tree[x] = Node{a, b};
    }
  }
  void build(int x, int l, int r) {
    tree[x].a = tree[x].b = 0;
    if (l == r) return;
    build(x << 1, l, ((l + r) >> 1));
    build(x << 1 | 1, ((l + r) >> 1) + 1, r);
  }
  long long query(int x, int l, int r, int p) {
    long long ans = tree[x].a * p + tree[x].b;
    if (l == r) return ans;
    if (p <= ((l + r) >> 1))
      ans = max(ans, query(x << 1, l, ((l + r) >> 1), p));
    else
      ans = max(ans, query(x << 1 | 1, ((l + r) >> 1) + 1, r, p));
    return ans;
  }
} T;
vector<int> G[1500010];
int n, m, dep[150005], mxdep;
int size[150005], rt, szf[150005];
int top;
long long a[150005], stk[6][150005], ans;
bool flag[150005];
void get_root(int node, int las, int tot) {
  size[node] = 1;
  szf[node] = 0;
  for (int to : G[node]) {
    if (to == las || flag[to]) continue;
    get_root(to, node, tot);
    size[node] += size[to];
    szf[node] = max(szf[node], size[to]);
  }
  szf[node] = max(szf[node], tot - size[node]);
  if (szf[rt] > szf[node]) rt = node;
}
void get_value(int node, long long val1, long long val2, long long sum,
               int from, int las) {
  if (node != rt && !from) from = node;
  dep[node] = dep[las] + 1;
  mxdep = max(mxdep, dep[node]);
  bool f = 0;
  for (int to : G[node]) {
    if (to == las || flag[to]) continue;
    f = 1;
    get_value(to, val1 + sum + a[to], val2 + a[to] * dep[node], sum + a[to],
              from, node);
  }
  if (!f) {
    stk[3][++top] = node;
    stk[0][top] = val1, stk[1][top] = val2, stk[2][top] = sum - a[rt],
    stk[4][top] = dep[node], stk[5][top] = from;
  }
}
void get_ans(int now) {
  flag[rt] = 1;
  mxdep = 0;
  top = 0;
  get_value(rt, a[rt], 0, a[rt], 0, 0);
  stk[3][++top] = rt;
  stk[0][top] = a[rt], stk[4][top] = 1,
  stk[1][top] = stk[2][top] = stk[5][top] = 0;
  T.build(1, 1, mxdep);
  stk[5][top + 1] = stk[5][0] = -1;
  for (int i = 1; i <= top;) {
    int j = i;
    while (stk[5][j] == stk[5][i])
      ans = max(ans, T.query(1, 1, mxdep, (int)stk[4][j]) + stk[0][j]), j++;
    j = i;
    while (stk[5][j] == stk[5][i])
      T.ins(1, 1, mxdep, stk[2][j], stk[1][j]), j++;
    i = j;
  }
  T.build(1, 1, mxdep);
  for (int i = top; i >= 1;) {
    int j = i;
    while (stk[5][j] == stk[5][i])
      ans = max(ans, T.query(1, 1, mxdep, (int)stk[4][j]) + stk[0][j]), j--;
    j = i;
    while (stk[5][j] == stk[5][i])
      T.ins(1, 1, mxdep, stk[2][j], stk[1][j]), j--;
    i = j;
  }
  int x = rt;
  for (int to : G[now]) {
    if (flag[to] || size[to] == 1) continue;
    int t = size[to];
    rt = 0;
    get_root(to, x, t);
    get_ans(rt);
  }
}
int main() {
  szf[0] = 2147483647;
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }
  for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
  get_root(1, 0, n);
  get_ans(rt);
  printf("%lld\n", ans);
  return 0;
}
