#include <bits/stdc++.h>
using ll = long long;
using namespace std;
struct subtree_info_t {
  int parent;
  int depth;
  int size;
  int height;
};
vector<subtree_info_t> prepare_subtree_info(vector<vector<int> > const& g,
                                            int root) {
  int n = g.size();
  vector<subtree_info_t> info(n, (subtree_info_t){-1, -1, -1, -1});
  vector<int> topological(n);
  topological[0] = root;
  info[root].parent = root;
  info[root].depth = 0;
  int r = 1;
  for (int l = 0; l < r; ++l) {
    int i = topological[l];
    for (int j : g[i])
      if (j != info[i].parent) {
        topological[r++] = j;
        info[j].parent = i;
        info[j].depth = info[i].depth + 1;
      }
  }
  while ((--r) >= 0) {
    int i = topological[r];
    info[i].size = 1;
    info[i].height = 0;
    for (int j : g[i])
      if (j != info[i].parent) {
        info[i].size += info[j].size;
        info[i].height = max(info[i].height, info[j].height + 1);
      }
  }
  info[root].parent = -1;
  return info;
}
template <typename TreeOperation>
vector<typename TreeOperation::type> fold_rooted_tree(
    vector<vector<int> > const& g, int root,
    TreeOperation op = TreeOperation()) {
  int n = g.size();
  vector<typename TreeOperation::type> data(n);
  stack<tuple<bool, int, int> > stk;
  stk.emplace(false, root, -1);
  while (not stk.empty()) {
    bool state;
    int x, parent;
    tie(state, x, parent) = stk.top();
    stk.pop();
    if (not state) {
      stk.emplace(true, x, parent);
      for (int y : g[x])
        if (y != parent) {
          stk.emplace(false, y, x);
        }
    } else {
      vector<pair<int, typename TreeOperation::type> > args;
      for (int y : g[x])
        if (y != parent) {
          args.emplace_back(y, data[y]);
        }
      data[x] = op(x, args);
    }
  };
  return data;
}
template <typename TreeOperation>
vector<typename TreeOperation::type> reroot_folded_rooted_tree(
    vector<typename TreeOperation::type> data, vector<vector<int> > const& g,
    int root, TreeOperation op = TreeOperation()) {
  stack<pair<int, int> > stk;
  stk.emplace(root, -1);
  while (not stk.empty()) {
    int x, parent;
    tie(x, parent) = stk.top();
    stk.pop();
    if (parent != -1) {
      data[x] = op.add(x, data[x], parent,
                       op.subtract(parent, data[parent], x, data[x]));
    }
    for (int y : g[x])
      if (y != parent) {
        stk.emplace(y, x);
      }
  }
  return data;
}
struct tree_operation {
  typedef struct {
    vector<int> height;
    vector<bool> has_favorite;
    vector<int> indices;
  } type;
  vector<bool> s;
  tree_operation(vector<bool> const& s) : s(s) {}
  type operator()(int i, vector<pair<int, type> > const& args) {
    type data = {};
    for (auto arg : args) {
      data = add(i, data, arg.first, arg.second);
    }
    return data;
  }
  type add(int i, type data_i, int j, type data_j) {
    data_i.height.push_back(
        1 + accumulate(begin(data_j.height), end(data_j.height), 0,
                       [&](int i, int j) { return max(i, j); }));
    data_i.has_favorite.push_back(
        s[j] or accumulate(begin(data_j.has_favorite), end(data_j.has_favorite),
                           false, logical_or<bool>()));
    data_i.indices.push_back(j);
    return data_i;
  }
  type subtract(int i, type data_i, int j, type data_j) {
    int k = find(begin(data_i.indices), end(data_i.indices), j) -
            data_i.indices.begin();
    data_i.height.erase(data_i.height.begin() + k);
    data_i.has_favorite.erase(data_i.has_favorite.begin() + k);
    data_i.indices.erase(data_i.indices.begin() + k);
    return data_i;
  }
};
ll solve(int n, vector<vector<int> > const& g, vector<bool> const& s) {
  if (n == 1) return 1;
  if (n == 2) return 3;
  constexpr int root = 0;
  auto info = prepare_subtree_info(g, root);
  auto data = reroot_folded_rooted_tree(
      fold_rooted_tree(g, 0, tree_operation(s)), g, root, tree_operation(s));
  ll cnt = 0;
  for (int i = 0; (i) < int(n); ++(i)) {
    int degree = g[i].size();
    if (degree == 1) {
      cnt += s[i];
    } else {
      vector<int> order(degree);
      iota(begin(order), end(order), 0);
      sort(begin(order), end(order), [&](int j1, int j2) {
        return data[i].height[j1] < data[i].height[j2];
      });
      int r = data[i].height[order[degree - 2]] + 1;
      int l = r;
      if (s[i]) {
        l = 0;
      } else {
        for (int j : order) {
          if (data[i].has_favorite[j]) {
            l = data[i].height[j];
            break;
          }
        }
      }
      cnt += r - l;
    }
  }
  for (int i = 0; (i) < int(n); ++(i)) {
    for (int j : g[i])
      if (i < j) {
        int i_in_j = find(begin(data[j].indices), end(data[j].indices), i) -
                     data[j].indices.begin();
        int j_in_i = find(begin(data[i].indices), end(data[i].indices), j) -
                     data[i].indices.begin();
        int i_height = data[j].height[i_in_j];
        int j_height = data[i].height[j_in_i];
        if (i_height < j_height) {
          cnt += data[j].has_favorite[i_in_j];
        } else if (i_height > j_height) {
          cnt += data[i].has_favorite[j_in_i];
        } else {
          cnt += data[j].has_favorite[i_in_j] or data[i].has_favorite[j_in_i];
        }
      }
  }
  return cnt;
}
int main() {
  int n;
  cin >> n;
  vector<vector<int> > g(n);
  for (int i = 0; (i) < int(n - 1); ++(i)) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  vector<bool> s(n);
  for (int i = 0; (i) < int(n); ++(i)) {
    char c;
    cin >> c;
    s[i] = c - '0';
  }
  ll answer = solve(n, g, s);
  cout << answer << endl;
  return 0;
}
