#include <bits/stdc++.h>
using namespace std;
const int MX = 150005;
const long long inf = 2e18;
bool Q = 0;
struct Line {
  mutable long long m, b, x;
  bool operator<(const Line ot) const { return Q ? x < ot.x : m < ot.m; }
};
long long ceil(long long a, long long b) {
  if (a < 0 != b < 0) return a / b;
  return (abs(a) + abs(b) - 1) / abs(b);
}
long long intersection(const Line &p, const Line &q) {
  return ceil(q.b - p.b, p.m - q.m);
}
struct Hull : multiset<Line> {
  bool valid(multiset<Line>::iterator it) {
    if (it == begin()) {
      auto sig = it;
      sig++;
      if (sig != end()) sig->x = intersection(*it, *sig);
      return it->x = -inf;
    }
    auto ant = it, sig = it;
    ant--, sig++;
    if (sig == end()) {
      it->x = intersection(*it, *ant);
      return 1;
    }
    long long x = intersection(*it, *ant);
    long long y = intersection(*it, *sig);
    if (x > y) return 0;
    it->x = x, sig->x = y;
    return 1;
  }
  void add(long long m, long long b) {
    auto it = lower_bound({m, b, -inf});
    if (it != end() && it->m == m) {
      if (it->b > b) return;
      it->b = b;
    } else {
      it = insert({m, b, -inf});
    }
    if (!valid(it)) {
      erase(it);
      return;
    }
    auto ant = it;
    while (ant != begin()) {
      if (valid(--ant)) break;
      erase(ant);
      if (it == begin()) {
        it->x = -inf;
        break;
      }
      ant = it;
    }
    auto sig = it;
    sig++;
    while (sig != end() && !valid(sig)) erase(sig++);
  }
  long long query(long long x) {
    if (empty()) return 0;
    Q = 1;
    auto it = upper_bound({0, 0, x});
    it--;
    Q = 0;
    return x * it->m + it->b;
  }
};
struct NODO {
  long long bajada, tot, depth, subida;
  NODO() {}
};
long long getsubida(NODO &parsol) {
  return parsol.tot * (parsol.depth + 2) - parsol.bajada;
}
vector<int> g[153456];
int valor[153456], hijos[153456];
int vnums[153456], cuniv;
bool marca[153456];
void dfs0(int num, int pa) {
  hijos[num] = 1;
  vnums[cuniv++] = num;
  for (int hijo : g[num]) {
    if (hijo == pa || marca[hijo]) continue;
    dfs0(hijo, num);
    hijos[num] += hijos[hijo];
  }
}
vector<NODO> acola;
NODO nuevo;
void dfs1(int num, int pa, long long bajada, long long tot, long long depth) {
  bajada += tot;
  nuevo.bajada = bajada;
  nuevo.tot = tot;
  nuevo.depth = depth;
  nuevo.subida = getsubida(nuevo);
  acola.push_back(nuevo);
  for (int v : g[num]) {
    if (marca[v] || v == pa) continue;
    dfs1(v, num, bajada, tot + valor[v], depth + 1);
  }
}
long long answer = 0;
void descomp(int num) {
  cuniv = 0;
  acola.clear();
  dfs0(num, num);
  int maxx, minn, centroide = num, nodo;
  minn = cuniv;
  for (int i = 0; i < cuniv; i++) {
    nodo = vnums[i];
    maxx = cuniv - hijos[nodo];
    for (int hijo : g[nodo]) {
      if (hijos[hijo] > hijos[nodo] || marca[hijo]) continue;
      maxx = max(maxx, hijos[hijo]);
    }
    if (minn > maxx) {
      minn = maxx;
      centroide = nodo;
    }
  }
  Hull dp;
  NODO parsol;
  long long asubida, amaxsubida = 0;
  for (int hijo : g[centroide]) {
    if (marca[hijo] == 1) continue;
    acola.clear();
    dfs1(hijo, centroide, valor[centroide], valor[centroide] + valor[hijo], 1);
    for (int i = 0; i < acola.size(); i++) {
      parsol = acola[i];
      answer = max(answer, parsol.bajada);
      asubida = parsol.subida;
      answer = max(answer, asubida);
      answer = max(answer, dp.query(parsol.tot) + parsol.subida);
    }
    for (int i = 0; i < acola.size(); i++) {
      parsol = acola[i];
      asubida = parsol.subida;
      parsol.bajada -= valor[centroide] * (parsol.depth + 1);
      amaxsubida = max(amaxsubida, asubida);
      dp.add(parsol.depth, parsol.bajada);
    }
  }
  dp.clear();
  for (int i = 0; i < g[centroide].size(); i++) {
    int hijo = g[centroide][g[centroide].size() - 1 - i];
    if (marca[hijo] == 1) continue;
    acola.clear();
    dfs1(hijo, centroide, valor[centroide], valor[centroide] + valor[hijo], 1);
    for (int i = 0; i < acola.size(); i++) {
      parsol = acola[i];
      answer = max(answer, parsol.bajada);
      answer = max(answer, parsol.subida);
      answer = max(answer, dp.query(parsol.tot) + parsol.subida);
    }
    for (int i = 0; i < acola.size(); i++) {
      parsol = acola[i];
      asubida = parsol.subida;
      parsol.bajada -= valor[centroide] * (parsol.depth + 1);
      dp.add(parsol.depth, parsol.bajada);
    }
  }
  marca[centroide] = 1;
  for (int hijo : g[centroide]) {
    if (marca[hijo]) continue;
    descomp(hijo);
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  int iz, der;
  for (int i = 0; i < n - 1; i++) {
    cin >> iz >> der;
    g[iz].push_back(der);
    g[der].push_back(iz);
  }
  for (int i = 1; i < n + 1; i++) {
    cin >> valor[i];
  }
  memset(marca, 0, sizeof marca);
  descomp(1);
  cout << answer << '\n';
}
