#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 150000;
struct L {
  long long upsum, sum;
  L() {}
  L(long long upsum, long long sum) : upsum(upsum), sum(sum) {}
};
bool operator<(const L& a, const L& b) {
  if (a.upsum != b.upsum) return a.upsum > b.upsum;
  return a.sum > b.sum;
}
struct R {
  long long downsum;
  int len;
  R() {}
  R(long long downsum, int len) : downsum(downsum), len(len) {}
};
bool operator<(const R& a, const R& b) {
  if (a.downsum != b.downsum) return a.downsum > b.downsum;
  return a.len > b.len;
}
struct Res {
  vector<L> l;
  vector<R> r;
  long long best;
};
int n;
vector<int> adj[MAXN];
int val[MAXN];
bool alive[MAXN];
int sz[MAXN];
void dfssz(int at, int par) {
  sz[at] = 1;
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (!alive[to] || to == par) continue;
    dfssz(to, at);
    sz[at] += sz[to];
  }
}
int dfscentroid(int at, int par, int rootsz) {
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (!alive[to] || to == par) continue;
    if (2 * sz[to] > rootsz) return dfscentroid(to, at, rootsz);
  }
  return at;
}
int centroid(int at) {
  dfssz(at, -1);
  return dfscentroid(at, -1, sz[at]);
}
L cl[MAXN];
int ncl;
R cr[MAXN];
int ncr;
void dfslr(int at, int par, int len, long long sum, long long downsum,
           long long upsum) {
  ++len;
  sum += val[at];
  downsum += sum;
  upsum += (long long)len * val[at];
  cl[ncl++] = L(upsum, sum);
  cr[ncr++] = R(downsum, len);
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (!alive[to] || to == par) continue;
    dfslr(to, at, len, sum, downsum, upsum);
  }
}
vector<L> merge(const vector<L>& a, const vector<L>& b) {
  vector<L> ret;
  int ai = 0, bi = 0;
  while (ai < ((int)(a).size()) || bi < ((int)(b).size())) {
    if (ai < ((int)(a).size()) && (bi >= ((int)(b).size()) || a[ai] < b[bi])) {
      if (((int)(ret).size()) == 0 || a[ai].sum > ret.back().sum)
        ret.push_back(a[ai]);
      ++ai;
    } else {
      if (((int)(ret).size()) == 0 || b[bi].sum > ret.back().sum)
        ret.push_back(b[bi]);
      ++bi;
    }
  }
  return ret;
}
vector<R> merge(const vector<R>& a, const vector<R>& b) {
  vector<R> ret;
  int ai = 0, bi = 0;
  while (ai < ((int)(a).size()) || bi < ((int)(b).size())) {
    if (ai < ((int)(a).size()) && (bi >= ((int)(b).size()) || a[ai] < b[bi])) {
      if (((int)(ret).size()) == 0 || a[ai].len > ret.back().len)
        ret.push_back(a[ai]);
      ++ai;
    } else {
      if (((int)(ret).size()) == 0 || b[bi].len > ret.back().len)
        ret.push_back(b[bi]);
      ++bi;
    }
  }
  return ret;
}
long long calc(const vector<L>& l, const vector<R>& r) {
  int k = 0;
  long long ret = LLONG_MIN;
  for (int j = (0); j < (((int)(l).size())); ++j) {
    long long cur = l[j].upsum + r[k].len * l[j].sum + r[k].downsum;
    while (k + 1 < ((int)(r).size())) {
      long long nxt = l[j].upsum + r[k + 1].len * l[j].sum + r[k + 1].downsum;
      if (nxt >= cur)
        ++k, cur = nxt;
      else
        break;
    }
    ret = max(ret, cur);
  }
  return ret;
}
Res rec(int root, const vector<int>& ch, int l, int r) {
  if (l == r) {
    int at = ch[l];
    if (at == root) {
      Res ret;
      ret.l = vector<L>(1, L(val[at], val[at]));
      ret.r = vector<R>(1, R(0, 0));
      ret.best = val[at];
      return ret;
    } else {
      ncl = 0, ncr = 0;
      dfslr(at, root, 1, val[root], val[root], val[root]);
      sort(cl, cl + ncl);
      {
        int tmp = 0;
        for (int j = (0); j < (ncl); ++j)
          if (tmp == 0 || cl[j].sum > cl[tmp - 1].sum) cl[tmp++] = cl[j];
        ncl = tmp;
      }
      for (int j = (0); j < (ncr); ++j)
        cr[j].downsum -= (long long)cr[j].len * val[root], --cr[j].len;
      sort(cr, cr + ncr);
      {
        int tmp = 0;
        for (int j = (0); j < (ncr); ++j)
          if (tmp == 0 || cr[j].len > cr[tmp - 1].len) cr[tmp++] = cr[j];
        ncr = tmp;
      }
      Res ret;
      ret.l = vector<L>(cl, cl + ncl);
      ret.r = vector<R>(cr, cr + ncr);
      ret.best = LLONG_MIN;
      return ret;
    }
  }
  int m = l + (r - l) / 2;
  Res lres = rec(root, ch, l, m);
  Res rres = rec(root, ch, m + 1, r);
  Res ret;
  ret.l = merge(lres.l, rres.l);
  ret.r = merge(lres.r, rres.r);
  ret.best = max(max(lres.best, rres.best),
                 max(calc(lres.l, rres.r), calc(rres.l, lres.r)));
  return ret;
}
long long calc(int root) {
  vector<int> ch;
  ch.push_back(root);
  for (int i = (0); i < (((int)(adj[root]).size())); ++i) {
    int to = adj[root][i];
    if (!alive[to]) continue;
    ch.push_back(to);
  }
  return rec(root, ch, 0, ((int)(ch).size()) - 1).best;
}
long long decompose(int at) {
  at = centroid(at);
  long long ret = calc(at);
  alive[at] = false;
  for (int i = (0); i < (((int)(adj[at]).size())); ++i) {
    int to = adj[at][i];
    if (!alive[to]) continue;
    long long cur = decompose(to);
    ret = max(ret, cur);
  }
  return ret;
}
long long solve() {
  for (int i = (0); i < (n); ++i) alive[i] = true;
  return decompose(0);
}
void run() {
  scanf("%d", &n);
  for (int i = (0); i < (n - 1); ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    --a, --b;
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  for (int i = (0); i < (n); ++i) scanf("%d", &val[i]);
  printf("%lld\n", solve());
}
void stress() {
  for (int rep = (0); rep < (100); ++rep) {
    n = 10;
    for (int i = (0); i < (n); ++i) adj[i].clear();
    for (int i = (1); i < (n); ++i) {
      int a = rand() % i, b = i;
      adj[a].push_back(b), adj[b].push_back(a);
    }
    for (int i = (0); i < (n); ++i) val[i] = rand() % 1000 + 1;
    long long ans = solve();
    printf("res=%lld\n", ans);
  }
}
int main() {
  run();
  return 0;
}
