#include <bits/stdc++.h>
using ll = long long;
template <class WeightType>
struct EdgeWithWeight {
  int to;
  WeightType weight;
  EdgeWithWeight() : to(0), weight() {}
  EdgeWithWeight(int to, const WeightType &weight) : to(to), weight(weight) {}
};
using Edge = EdgeWithWeight<int>;
template <typename EdgeType>
class AdjacencyList {
 public:
 private:
  std::vector<std::vector<EdgeType>> m_lists;

 public:
  explicit AdjacencyList(int n = 0) : m_lists(n) {}
  int size() const { return m_lists.size(); }
  template <typename... Args>
  void add_edge(int u, Args &&...args) {
    m_lists[u].emplace_back(args...);
  }
  const std::vector<EdgeType> &operator[](int u) const { return m_lists[u]; }
  std::vector<EdgeType> &operator[](int u) { return m_lists[u]; }
};
template <class T, int K, class Comparator = std::less<T>>
class TopK {
 private:
  Comparator m_comparator;
  int m_count;
  T m_buffer[K];

 public:
  explicit TopK(const Comparator &cmp = Comparator())
      : m_comparator(cmp), m_count(0), m_buffer() {}
  void insert(const T &x) {
    if (m_count == K && m_comparator(m_buffer[K - 1], x)) {
      return;
    }
    if (m_count < K) {
      ++m_count;
    }
    m_buffer[m_count - 1] = x;
    for (int i = m_count - 2; i >= 0; --i) {
      if (m_comparator(m_buffer[i + 1], m_buffer[i])) {
        std::swap(m_buffer[i + 1], m_buffer[i]);
      }
    }
  }
  const T &operator[](size_t i) const { return m_buffer[i]; }
  size_t size() const { return m_count; }
};
template <class EdgeType>
class TreeFarthestTable {
 public:
  typedef decltype(EdgeType().weight) weight_type;

 private:
  std::vector<int> m_farthest_vertices;
  std::vector<weight_type> m_farthest_weights;

 public:
  TreeFarthestTable(
      const AdjacencyList<EdgeType> &graph = AdjacencyList<EdgeType>())
      : m_farthest_vertices(graph.size()), m_farthest_weights(graph.size()) {
    const int n = graph.size();
    std::vector<int> parent(n, -1), parent_weight(n);
    std::vector<TopK<std::pair<weight_type, int>, 2,
                     std::greater<std::pair<weight_type, int>>>>
        result(n);
    std::stack<std::pair<int, int>> stack;
    stack.push(std::make_pair(0, 0));
    parent[0] = 0;
    while (!stack.empty()) {
      auto &frame = stack.top();
      const int u = frame.first;
      if (frame.second == 0) {
        for (const auto &e : graph[u]) {
          if (parent[e.to] >= 0) {
            continue;
          }
          parent[e.to] = u;
          parent_weight[e.to] = e.weight;
          stack.push(std::make_pair(e.to, 0));
        }
        frame.second = 1;
      } else {
        result[u].insert(std::pair<weight_type, int>(weight_type(), u));
        for (const auto &e : graph[u]) {
          if (e.to == parent[u]) {
            continue;
          }
          const auto w = result[e.to][0];
          result[u].insert(
              std::pair<weight_type, int>(w.first + e.weight, w.second));
        }
        stack.pop();
      }
    }
    std::queue<int> queue;
    queue.push(0);
    while (!queue.empty()) {
      const int u = queue.front(), p = parent[u];
      queue.pop();
      for (const auto &e : graph[u]) {
        if (e.to != p) {
          queue.push(e.to);
        }
      }
      if (u == 0) {
        continue;
      }
      const weight_type &pw = parent_weight[u];
      const int k = (result[u][0].first + pw == result[p][0].first ? 1 : 0);
      const std::pair<weight_type, int> &w = result[p][k];
      result[u].insert(std::pair<weight_type, int>(w.first + pw, w.second));
    }
    for (int i = 0; i < n; ++i) {
      m_farthest_weights[i] = result[i][0].first;
      m_farthest_vertices[i] = result[i][0].second;
    }
  }
  const std::vector<int> &vertices() const { return m_farthest_vertices; }
  int vertice(int v) const { return m_farthest_vertices[v]; }
  const std::vector<weight_type> &weights() const { return m_farthest_weights; }
  weight_type weight(int v) const { return m_farthest_weights[v]; }
};
using namespace std;
static int subtree_depth(vector<int> &result, int u, int p,
                         AdjacencyList<Edge> &graph) {
  int d = 1;
  for (const auto &e : graph[u]) {
    if (e.to == p) {
      continue;
    }
    d = max(d, subtree_depth(result, e.to, u, graph) + 1);
  }
  result[u] = d;
  return d;
}
int main() {
  ios_base::sync_with_stdio(false);
  int n;
  cin >> n;
  AdjacencyList<Edge> graph(n);
  for (int i = 1; i < n; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    graph.add_edge(a, b, 1);
    graph.add_edge(b, a, 1);
  }
  string s;
  cin >> s;
  TreeFarthestTable<Edge> farthest(graph);
  vector<int> depths(n);
  subtree_depth(depths, 0, -1, graph);
  ll answer = farthest.weight(0) + 1;
  for (int u = 1; u < n; ++u) {
    answer += min(depths[u] + 1, farthest.weight(u));
  }
  cout << answer << endl;
  return 0;
}
