#include <bits/stdc++.h>
using namespace std;
const int MAX = 150010;
long long arr[MAX];
int sz[MAX], erased[MAX], vis[4 * MAX], deg[MAX];
int n;
vector<vector<int> > adj(MAX), adj2(MAX);
struct Line {
  long long x, y;
  long long f(long long a) { return a * x + y; }
};
Line tree[4 * MAX];
int t = 0, L = 0, R = MAX - 2;
void clearTree(int node, int l, int r) {
  tree[node].x = 0, tree[node].y = -4e18;
  if (l == r) return;
  int mid = (l + r) >> 1;
  if (vis[node * 2] == t) clearTree(node * 2, l, mid);
  if (vis[node * 2 + 1] == t) clearTree(node * 2 + 1, mid + 1, r);
}
void clear() {
  clearTree(1, L, R);
  t++;
}
void insert(int node, int l, int r, Line li) {
  vis[node] = t;
  int mid = (l + r) >> 1;
  bool lef = (li.f(l) > tree[node].f(l));
  bool midd = (li.f(mid) > tree[node].f(mid));
  if (midd) swap(tree[node], li);
  if (l == r) return;
  if (lef != mid)
    insert(node * 2, l, mid, li);
  else
    insert(node * 2 + 1, mid + 1, r, li);
}
long long query(int node, int l, int r, long long a) {
  int mid = (l + r) >> 1;
  if (l == r)
    return tree[node].f(a);
  else if (a < mid)
    return max(tree[node].f(a), query(node * 2, l, mid, a));
  else
    return max(tree[node].f(a), query(node * 2 + 1, mid + 1, r, a));
}
long long ans = 0ll;
int dfs2(int node, int par, int sub_sz) {
  for (auto &child : adj[node]) {
    if (sz[child] > sub_sz / 2 && child != par && !erased[child])
      return dfs2(child, node, sub_sz);
  }
  return node;
}
void dfs1(int node, int par) {
  sz[node] = 1;
  for (auto &child : adj[node]) {
    if (child == par || erased[child]) continue;
    dfs1(child, node);
    sz[node] += sz[child];
  }
}
long long dfs(int node, int par, bool flag, int cnt, long long a, long long b,
              long long sum) {
  a += arr[node] * cnt;
  sum += arr[node];
  b += sum;
  long long x = max(a, b);
  if (flag && deg[node] == 1) {
    Line li;
    li.x = sum, li.y = a;
    insert(1, L, R, li);
  } else if (!flag && deg[node] == 1)
    x = max(x, query(1, L, R, cnt) + b);
  for (auto &child : adj[node]) {
    if (child == par || erased[child]) continue;
    x = max(x, dfs(child, node, flag, cnt + 1, a, b, sum));
  }
  return x;
}
void solve(int node) {
  clear();
  ans = max(ans, arr[node]);
  for (int i = 0; i < adj[node].size(); ++i) {
    if (erased[adj[node][i]]) continue;
    ans = max(ans, dfs(adj[node][i], node, 0, 1, 0ll, 0ll, 0ll));
    ans = max(ans,
              dfs(adj[node][i], node, 1, 2, arr[node], arr[node], arr[node]));
  }
  clear();
  for (int i = adj[node].size() - 1; i >= 0; --i) {
    if (erased[adj[node][i]]) continue;
    ans = max(ans, dfs(adj[node][i], node, 0, 1, 0ll, 0ll, 0ll));
    ans = max(ans,
              dfs(adj[node][i], node, 1, 2, arr[node], arr[node], arr[node]));
  }
}
void Centroid_Decomposition(int node) {
  dfs1(node, -1);
  int centroid = dfs2(node, -1, sz[node]);
  erased[centroid] = 1;
  for (auto &child : adj[node]) deg[child]--;
  solve(centroid);
  for (auto &child : adj[centroid]) {
    if (erased[child]) continue;
    Centroid_Decomposition(child);
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n;
  for (int i = 0; i < n - 1; ++i) {
    int x, y;
    cin >> x >> y;
    adj[x].push_back(y);
    adj[y].push_back(x);
    deg[x]++, deg[y]++;
  }
  for (int i = 1; i <= n; ++i) cin >> arr[i];
  Centroid_Decomposition(1);
  return cout << ans << "\n", 0;
}
