#include <bits/stdc++.h>
using LL = long long;
constexpr LL kIsQuery = -(1LL << 62);
struct Line {
  LL m, b;
  mutable std::function<const Line *()> succ;
  bool operator<(const Line &rhs) const {
    if (rhs.b != kIsQuery) return m < rhs.m;
    const Line *s = succ();
    if (!s) return false;
    LL x = rhs.m;
    return b - s->b < (s->m - m) * x;
  }
};
std::string to_string(const Line &line) {
  return "Line{" + std::to_string(line.m) + ", " + std::to_string(line.b) + "}";
}
struct DynamicHull : public std::multiset<Line> {
  bool bad(iterator y) {
    auto z = next(y);
    if (y == begin()) {
      if (z == end()) return false;
      return y->m == z->m && y->b <= z->b;
    }
    auto x = prev(y);
    if (z == end()) return y->m == x->m && y->b <= x->b;
    return (x->b - y->b) * (z->m - y->m) >= (y->b - z->b) * (y->m - x->m);
  }
  void insert_line(LL m, LL b) {
    auto y = insert({m, b});
    y->succ = [=] { return next(y) == end() ? nullptr : &*next(y); };
    if (bad(y)) {
      erase(y);
      return;
    }
    while (next(y) != end() && bad(next(y))) erase(next(y));
    while (y != begin() && bad(prev(y))) erase(prev(y));
  }
  LL eval(LL x) {
    auto l = *lower_bound(Line{x, kIsQuery});
    return l.m * x + l.b;
  }
};
DynamicHull hull;
const int kN = 150000 + 5;
std::vector<int> edges[kN];
int n;
int a[kN];
LL result = 0;
bool vis[kN];
int parent[kN];
int sz[kN];
int que[kN];
int balance[kN];
int bfs(int source, int fa = -1) {
  int qf = 0, qe = 0;
  que[qe++] = source;
  parent[source] = fa;
  while (qf != qe) {
    int u = que[qf++];
    sz[u] = 1;
    balance[u] = 0;
    for (int v : edges[u]) {
      if (!vis[v] && parent[u] != v) {
        parent[v] = u;
        que[qe++] = v;
      }
    }
  }
  for (int i = qe - 1; i >= 0; --i) {
    int u = que[i];
    if (i) {
      sz[parent[u]] += sz[u];
      balance[parent[u]] = std::max(balance[parent[u]], sz[u]);
    }
    balance[u] = std::max(balance[u], qe - sz[u]);
  }
  return qe;
}
LL dfs(int u, int fa, LL sum, LL pssum, int cnt) {
  ++cnt;
  sum += a[u];
  pssum += a[u] * 1LL * cnt;
  LL ret = hull.eval(sum) + pssum;
  for (int v : edges[u])
    if (v != fa && !vis[v]) {
      ret = std::max(ret, dfs(v, u, sum, pssum, cnt));
    }
  return ret;
}
void dfs2(int u, int fa, LL sum, LL pssum, int cnt) {
  sum += a[u];
  pssum += sum;
  ++cnt;
  hull.insert_line(cnt, pssum);
  for (int v : edges[u])
    if (v != fa && !vis[v]) {
      dfs2(v, u, sum, pssum, cnt);
    }
}
void divide(int root) {
  int tot = bfs(root);
  for (int i = tot - 1; i > 0; --i) {
    int u = que[i];
    if (balance[u] < balance[root]) {
      root = u;
    }
  }
  bfs(root);
  result = std::max<LL>(result, a[root]);
  for (int side = 0; side < 2; ++side) {
    hull.clear();
    std::reverse(edges[root].begin(), edges[root].end());
    hull.insert_line(1, a[root]);
    for (int v : edges[root])
      if (!vis[v]) {
        LL val = dfs(v, root, 0, 0, 0);
        1145141919810;
        1145141919810;
        result = std::max(result, val);
        dfs2(v, root, a[root], a[root], 1);
      }
  }
  vis[root] = true;
  for (int u : edges[root]) {
    if (!vis[u]) {
      divide(u);
    }
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 0; i < n - 1; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    edges[x].emplace_back(y);
    edges[y].emplace_back(x);
  }
  for (int i = 0; i < n; ++i) {
    scanf("%d", &a[i]);
  }
  divide(0);
  printf("%lld\n", result);
}
