#include <bits/stdc++.h>
using namespace std;
namespace CHT {
template <typename T>
T cross(complex<T> a, complex<T> b) {
  return imag(conj(a) * b);
}
template <typename T>
T dot(complex<T> a, complex<T> b) {
  return real(conj(a) * b);
}
struct __Query {
  static bool query;
};
bool __Query::query = false;
template <typename T>
struct Point {
  complex<T> p;
  mutable function<const complex<T> *()> succ;
  bool operator<(const Point &rhs) const {
    const complex<T> &q = rhs.p;
    if (!__Query::query) {
      if (real(p) != real(q)) return real(p) < real(q);
      return imag(p) < imag(q);
    }
    const complex<T> *s = succ();
    if (!s) return false;
    return dot(p - *s, q) < 0;
  }
};
template <typename T, int turn>
struct half_hull : public set<Point<T>> {
  using set<Point<T>>::begin;
  using set<Point<T>>::insert;
  using set<Point<T>>::end;
  using set<Point<T>>::lower_bound;
  using set<Point<T>>::empty;
  using set<Point<T>>::erase;
  using typename set<Point<T>>::iterator;
  complex<T> extreme(const complex<T> &p) const {
    assert(!empty() && turn * imag(p) >= 0);
    __Query::query = true;
    auto pos = lower_bound(Point<T>{p});
    __Query::query = false;
    assert(pos != end());
    return pos->p;
  }
  void insert(const complex<T> &p) {
    auto y = insert(Point<T>{p}).first;
    if (y == end()) return;
    y->succ = [=] { return next(y) == end() ? nullptr : &next(y)->p; };
    if (bad(y)) {
      erase(y);
      return;
    }
    while (y != begin() && bad(prev(y))) erase(prev(y));
    while (next(y) != end() && bad(next(y))) erase(next(y));
  }

 private:
  bool bad(iterator y) {
    if (y == begin() || y == end()) return false;
    auto x = prev(y), z = next(y);
    if (z == end()) return false;
    return cross(y->p - x->p, z->p - x->p) * turn >= 0;
  }
};
template <typename T>
struct convex_hull_trick {
  void insert(const complex<T> &p) {
    lower_hull.insert(p);
    upper_hull.insert(p);
  }
  long long extreme(const complex<T> &p) const {
    if (std::imag(p) < 0) return dot(lower_hull.extreme(p), p);
    return dot(upper_hull.extreme(p), p);
  }

 private:
  half_hull<T, +1> upper_hull;
  half_hull<T, -1> lower_hull;
};
}  // namespace CHT
using namespace CHT;
struct info {
  long long up = 0, down = 0, sum = 0, lenght = 0;
  void add(long long x) {
    ++lenght;
    up += (lenght + 1) * x;
    sum += x;
    down += sum;
  }
};
struct centroid_descomposition {
  int n;
  vector<bool> del;
  vector<vector<int>> adj;
  vector<int> size, parent;
  vector<vector<pair<int, int>>> anc;
  vector<int> data;
  vector<vector<int>> sub;
  vector<info> inf;
  long long ans = 0;
  centroid_descomposition(int n)
      : n(n), del(n), adj(n), size(n), parent(n), anc(n), data(n), inf(n){};
  void add_edge(int u, int v) {
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  int centroid(int u) {
    vector<int> seen = {u};
    parent[u] = -1;
    for (size_t i = 0; i < seen.size(); ++i) {
      u = seen[i];
      for (int v : adj[u])
        if (!del[v] && v != parent[u]) parent[v] = u, seen.push_back(v);
    }
    for (int sz = seen.size(), i = sz - 1, mx = 0; i >= 0; --i, mx = 0) {
      size[u = seen[i]] = 1;
      for (int v : adj[u])
        if (!del[v] && v != parent[u])
          size[u] += size[v], mx = max(mx, size[v]);
      if (max(sz - size[u], mx) <= sz / 2) return u;
    }
    return -1;
  }
  void dfs(int u, int p, int d, int c, info f) {
    if (p != -1) {
      f.add(data[u]);
      inf[u] = f;
      sub.back().push_back(u);
    } else
      sub.clear();
    anc[u].push_back({c, d});
    for (int v : adj[u])
      if (!del[v] && v != p) {
        if (p == -1) sub.push_back(vector<int>());
        dfs(v, u, d + 1, c, f);
      }
  }
  void rootify(int r) {
    int c = centroid(r);
    assert(c != -1);
    del[c] = true;
    dfs(c, -1, 0, c, info());
    for (int k = 0; k < 2; k++) {
      convex_hull_trick<long long> ch1;
      ch1.insert(complex<long long>(data[c], data[c]));
      for (auto &i : sub) {
        for (auto &j : i)
          ans = max(ans, ch1.extreme(complex<long long>(inf[j].lenght, 1)) +
                             inf[j].down);
        for (auto &j : i)
          ch1.insert(
              complex<long long>(inf[j].sum + data[c], inf[j].up + data[c]));
      }
      reverse(sub.begin(), sub.end());
    }
    for (int v : adj[c])
      if (!del[v]) rootify(v);
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  centroid_descomposition cd(n);
  for (int i = 0; i < n - 1; i++) {
    int x, y;
    cin >> x >> y;
    --x;
    --y;
    cd.add_edge(x, y);
  }
  for (int i = 0; i < n; i++) cin >> cd.data[i];
  cd.rootify(0);
  cout << cd.ans << '\n';
  return 0;
}
