#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
int M;
struct CHT {
  struct Node {
    pii L;
    int l, r;
    Node() : L(pii(0, -1e18)), l(-1), r(-1) {}
  };
  vector<Node> A;
  int cnt;
  ll f(pii L, int x) { return L.first * x + L.second; }
  void update(int nn, int s, int e, pii L2) {
    pii &L1 = A[nn].L;
    if (f(L1, s) < f(L2, s)) swap(L1, L2);
    if (f(L1, e) >= f(L2, e)) return;
    int m = s + e >> 1;
    if (f(L1, m) < f(L2, m)) {
      swap(L1, L2);
      if (A[nn].l < 0) {
        A[nn].l = ++cnt;
        A[A[nn].l].L = L1;
      }
      update(A[nn].l, s, m, L2);
    } else {
      if (A[nn].r < 0) {
        A[nn].r = ++cnt;
        A[A[nn].r].L = L1;
      }
      update(A[nn].r, m + 1, e, L2);
    }
  }
  void update(ll a, ll b) { update(0, 0, M, pii(a, b)); }
  ll query(int nn, int s, int e, int x) {
    if (nn < 0 || s > x || e < x) return -1e18;
    ll ret = f(A[nn].L, x);
    int m = s + e >> 1;
    return max({ret, query(A[nn].l, s, m, x), query(A[nn].r, m + 1, e, x)});
  }
  ll query(int x) { return query(0, 0, M, x); }
} cht1, cht2;
vector<int> edge[150005];
int sz[150005];
bool vis[150005];
int szf(int x, int p) {
  sz[x] = 1;
  for (auto i : edge[x])
    if (i != p && !vis[i]) sz[x] += szf(i, x);
  return sz[x];
}
int get_cen(int x, int p, int bar) {
  for (auto i : edge[x])
    if (i != p && !vis[i] && bar <= sz[i]) return get_cen(i, x, bar);
  return x;
}
int A[150005];
ll D[150005];
void dfs1(int x, int p, ll sum, int cnt, vector<pii> &v) {
  D[x] = D[p] + sum;
  v.emplace_back(D[x], cnt);
  for (auto i : edge[x])
    if (!vis[i] && i != p) {
      dfs1(i, x, sum + A[i], cnt + 1, v);
    }
}
void dfs2(int x, int p, ll sum, int cnt, vector<pii> &v) {
  D[x] = D[p] + 1ll * cnt * A[x];
  v.emplace_back(sum, D[x]);
  for (auto i : edge[x])
    if (!vis[i] && i != p) {
      dfs2(i, x, sum + A[i], cnt + 1, v);
    }
}
ll CD(int x) {
  x = get_cen(x, x, szf(x, x) + 1 >> 1);
  cht1.A.clear();
  cht2.A.clear();
  vis[x] = 1;
  ll ans = 0;
  M = szf(x, x);
  cht1.A.resize(2 * M);
  cht2.A.resize(2 * M);
  cht1.cnt = cht2.cnt = 0;
  vector<vector<pii> > a, b;
  vector<pii> v;
  D[x] = 0;
  for (auto i : edge[x])
    if (!vis[i]) {
      v.clear();
      dfs1(i, x, A[i], 1, v);
      a.push_back(v);
    }
  v.clear();
  v.emplace_back(0, 0);
  a.push_back(v);
  for (auto i : edge[x])
    if (!vis[i]) {
      v.clear();
      dfs2(i, x, A[i], 1, v);
      b.push_back(v);
    }
  v.clear();
  v.emplace_back(0, 0);
  b.push_back(v);
  for (int i = 0; i < a.size(); ++i) {
    if (i)
      for (auto j : b[i - 1]) cht1.update(j.first, j.second);
    for (auto j : a[i]) {
      ans = max(ans, j.first + 1ll * (j.second + 1) * A[x] +
                         cht1.query(j.second + 1));
    }
  }
  for (int i = (int)a.size() - 1; i >= 0; --i) {
    if (i + 1 < a.size())
      for (auto j : b[i + 1]) cht2.update(j.first, j.second);
    for (auto j : a[i])
      ans = max(ans, j.first + 1ll * (j.second + 1) * A[x] +
                         cht2.query(j.second + 1));
  }
  for (auto i : edge[x])
    if (!vis[i]) ans = max(ans, CD(i));
  return ans;
}
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  int N;
  cin >> N;
  for (int i = 1; i < N; ++i) {
    int x, y;
    cin >> x >> y;
    edge[x].push_back(y);
    edge[y].push_back(x);
  }
  for (int i = 1; i <= N; ++i) cin >> A[i];
  cout << CD(1);
  return 0;
}
