#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 (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);
  }
  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;
struct Edge {
  int to;
  int nxt;
} e[300005];
int n, m, edgenum, head[150005], dep[150005], maxd;
int pa[150005], size[150005], root, maxs[150005];
int st[150005], top;
long long a[150005], v1[150005], v2[150005], l[150005], s[150005], x[150005],
    maxv[150005], ans;
bool flag[150005];
void add(int u, int v) {
  e[++edgenum].to = v;
  e[edgenum].nxt = head[u];
  head[u] = edgenum;
}
void getroot(int node, int tot) {
  size[node] = 1;
  maxs[node] = 0;
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node] || flag[to]) continue;
    pa[to] = node;
    getroot(to, tot);
    size[node] += size[to];
    maxs[node] = max(maxs[node], size[to]);
  }
  maxs[node] = max(maxs[node], tot - size[node]);
  if (maxs[root] > maxs[node]) root = node;
  pa[node] = 0;
}
void dfs(int node, long long val1, long long val2, long long sum, int from) {
  if (node != root && !from) from = node;
  dep[node] = dep[pa[node]] + 1;
  maxd = max(maxd, dep[node]);
  bool f = 0;
  size[node] = 1;
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node] || flag[to]) continue;
    pa[to] = node;
    f = 1;
    dfs(to, val1 + sum + a[to], val2 + a[to] * dep[node], sum + a[to], from);
    size[node] += size[to];
  }
  if (!f) {
    st[++top] = node;
    v1[top] = val1, v2[top] = val2, s[top] = sum - a[root], l[top] = dep[node],
    x[top] = from;
  }
}
void solve() {
  flag[root] = 1;
  maxd = 0;
  top = 0;
  pa[root] = 0;
  dfs(root, a[root], 0, a[root], 0);
  st[++top] = root;
  v1[top] = a[root], l[top] = 1, v2[top] = s[top] = x[top] = 0;
  T.build(1, 1, maxd);
  x[top + 1] = x[0] = -1;
  for (int i = 1; i <= top;) {
    int j = i;
    while (x[j] == x[i])
      ans = max(ans, T.query(1, 1, maxd, (int)l[j]) + v1[j]), j++;
    j = i;
    while (x[j] == x[i]) T.ins(1, 1, maxd, s[j], v2[j]), j++;
    i = j;
  }
  T.build(1, 1, maxd);
  for (int i = top; i >= 1;) {
    int j = i;
    while (x[j] == x[i])
      ans = max(ans, T.query(1, 1, maxd, (int)l[j]) + v1[j]), j--;
    j = i;
    while (x[j] == x[i]) T.ins(1, 1, maxd, s[j], v2[j]), j--;
    i = j;
  }
  int x = root;
  for (int hd = head[x]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (flag[to] || size[to] == 1) continue;
    int t = size[to];
    root = 0;
    getroot(to, t);
    solve();
  }
}
int main() {
  maxs[0] = 2147483647;
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    add(u, v);
    add(v, u);
  }
  for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
  getroot(1, n);
  solve();
  printf("%lld\n", ans);
  return 0;
}
