#include <bits/stdc++.h>
#pragma GCC optimize("-O3")
using namespace std;
using VS = vector<string>;
using LL = long long;
using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
using VL = vector<LL>;
using VVL = vector<VL>;
const int INF = 1e9;
const LL LINF = 1e16;
const LL MOD = 1000000007;
const double PI = acos(-1.0);
int DX[8] = {0, 0, 1, -1, 1, 1, -1, -1};
int DY[8] = {1, -1, 0, 0, 1, -1, 1, -1};
template <class N, class E>
struct Rerooting {
  int n;
  const vector<vector<E>>& G;
  vector<N> subtreesum;
  vector<vector<N>> dp;
  vector<unordered_map<int, N>> edgememo;
  void dfs1(int v, int p) {
    subtreesum[v] = N();
    for (auto e : G[v]) {
      int nx = e.to;
      if (nx == p) continue;
      dfs1(nx, v);
      subtreesum[v] = subtreesum[v] + subtreesum[nx].include_e(v, e);
    }
    subtreesum[v] = subtreesum[v].include_v(v);
  }
  void dfs2(int v, int p, N top) {
    int deg = int(G[v].size());
    dp[v] = vector<N>(deg + 1);
    dp[v][0] = N();
    for (int i = 0; i < deg; i++) {
      int nx = G[v][i].to;
      dp[v][i + 1] =
          dp[v][i] + (nx == p ? top : subtreesum[nx]).include_e(v, G[v][i]);
    }
    N rnode = N();
    dp[v].back() = dp[v].back().include_v(v);
    for (int i = deg - 1; i >= 0; i--) {
      dp[v][i] = (dp[v][i] + rnode).include_v(v);
      int nx = G[v][i].to;
      edgememo[v][nx] = dp[v][i];
      if (nx != p) dfs2(nx, v, dp[v][i]);
      rnode = rnode + (nx == p ? top : subtreesum[nx]).include_e(v, G[v][i]);
    }
  }
  Rerooting(const vector<vector<E>>& _g, int root)
      : n(int(_g.size())),
        G(_g),
        subtreesum(n),
        dp(n),
        edgememo(int(_g.size())) {
    dfs1(root, -1);
    dfs2(root, -1, N());
  }
};
template <class N, class E>
vector<vector<N>> Rerooting_get(const vector<vector<E>>& g, int root) {
  return Rerooting<N, E>(g, root).dp;
}
inline int ri() {
  int in;
  int y = scanf("%d", &in);
  return in;
}
inline LL ril() {
  LL in;
  int y = scanf("%lld", &in);
  return in;
}
inline void oi(LL out) { printf("%lld\n", out); }
int main() {
  struct Edge {
    int to;
    Edge(int t) : to(t) {}
  };
  int N = ri();
  vector<vector<Edge>> G(2 * N);
  vector<PII> edge(N - 1);
  for (int(i) = (0); (i) < (N - 1); (i)++) {
    int a = ri() - 1, b = ri() - 1;
    G[a].push_back(Edge(b));
    G[b].push_back(Edge(a));
    edge[i] = PII(a, b);
  }
  static string s;
  cin >> s;
  struct Node {
    PLL d;
    int onecnt;
    Node() : d(PLL(0, 0)), onecnt(0) {}
    Node include_e(int, const Edge&) const {
      Node res = *this;
      res.d.second = 0;
      res.d.first++;
      return res;
    }
    Node operator+(const Node& r) const {
      Node res = *this;
      for (auto it : {r.d.first, r.d.second}) {
        if (res.d.first < it) {
          res.d.second = res.d.first;
          res.d.first = it;
        } else if (res.d.second < it) {
          res.d.second = it;
        }
      }
      res.onecnt += r.onecnt;
      return res;
    }
    Node include_v(int v) const {
      Node res = *this;
      if (s[v] == '1') res.onecnt++;
      return res;
    }
  };
  auto all_tree = Rerooting<Node, Edge>(G, 0);
  auto tree_dp_v = all_tree.dp;
  auto tree_dp_e = all_tree.edgememo;
  LL ans = 0;
  for (int(i) = (0); (i) < (N); (i)++) {
    LL OK = tree_dp_v[i].back().d.second;
    LL DW = INF;
    ;
    for (auto it : tree_dp_v[i]) {
      if (it.onecnt) DW = min(DW, it.d.first);
    }
    if (s[i] == '1') DW = 0;
    ;
    if (DW <= OK) ans += OK - DW + 1;
  };
  for (int(i) = (0); (i) < (N - 1); (i)++) {
    int a, b;
    tie(a, b) = edge[i];
    Node d1 = tree_dp_e[a][b];
    Node d2 = tree_dp_e[b][a];
    ;
    if (d1.d.first > d2.d.first) {
      ans += d2.onecnt > 0;
    } else if (d1.d.first < d2.d.first) {
      ans += d1.onecnt > 0;
    } else
      ans++;
  }
  oi(ans);
  return 0;
}
