#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
template <class T>
using V = vector<T>;
template <class T>
using VV = vector<vector<T>>;
template <class T, class U>
void chmax(T& x, U y) {
  if (x < y) x = y;
}
template <class T, class U>
void chmin(T& x, U y) {
  if (y < x) x = y;
}
template <class T>
void mkuni(V<T>& v) {
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()), v.end());
}
template <class S, class T>
ostream& operator<<(ostream& o, const pair<S, T>& p) {
  return o << "(" << p.first << "," << p.second << ")";
}
template <class T>
ostream& operator<<(ostream& o, const vector<T>& vc) {
  o << "{";
  for (const T& v : vc) o << v << ",";
  o << "}";
  return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
namespace Normalize {
template <class E>
void dfs(vector<vector<E>>& G, vector<int>& ord, int v, int p = -1) {
  ord.emplace_back(v);
  int K = G[v].size();
  for (int i = 0; i < int(K); i++) {
    if (G[v][i].to == p) {
      rotate(G[v].begin() + i, G[v].begin() + i + 1, G[v].end());
      K--;
      break;
    }
  }
  for (int i = 0; i < int(K); i++) {
    dfs(G, ord, G[v][i].to, v);
  }
}
template <class E>
vector<int> normalize_and_gettopord(vector<vector<E>>& G, int r = 0) {
  vector<int> ord;
  dfs(G, ord, r);
  return ord;
}
}  // namespace Normalize
template <class N>
struct BidirectionalTreeDP {
  vector<N> dp;
  vector<N> up;
  vector<N> rp;
  vector<int> par;
  template <class E>
  BidirectionalTreeDP(vector<vector<E>>& G, int r = 0) {
    int V = G.size();
    dp.assign(V, N());
    up.assign(V, N());
    rp.assign(V, N());
    par.assign(V, 0);
    vector<int> ord = Normalize::normalize_and_gettopord<E>(G, r);
    for (int t = 0; t < int(V); t++) {
      int v = ord[t];
      if (v == r)
        par[v] = -1;
      else
        par[v] = G[v].back().to;
    }
    for (int t = V - 1; t >= 0; t--) {
      int v = ord[t];
      dp[v] = N();
      int K = G[v].size() - (v != r);
      for (int i = 0; i < int(K); i++) {
        const E& e = G[v][i];
        int u = e.to;
        dp[v] = dp[v] + dp[u].append_edge(v, e);
      }
      dp[v].finalize(v);
    }
    for (int t = 0; t < int(V); t++) {
      int v = ord[t];
      int K = G[v].size() - (v != r);
      vector<N> ls(K + 1), rs(K + 1);
      for (int i = 0; i < int(K); i++) {
        ls[i + 1] = ls[i] + dp[G[v][i].to].append_edge(v, G[v][i]);
        rs[K - 1 - i] =
            dp[G[v][K - 1 - i].to].append_edge(v, G[v][K - 1 - i]) + rs[K - i];
      }
      for (int i = 0; i < int(K); i++) {
        const E& e = G[v][i];
        int u = e.to;
        up[u] = ls[i] + rs[i + 1];
        if (v != r) up[u] = up[u] + up[v].append_edge(v, G[v].back());
        up[u].finalize(v);
      }
      rp[v] = ls[K];
      if (v != r) rp[v] = rp[v] + up[v].append_edge(v, G[v].back());
      rp[v].finalize(v);
    }
  }
  N get(int v, int p = -1) {
    if (p == -1) return rp[v];
    if (par[v] == p) return dp[v];
    return up[p];
  }
};
struct Node {
  bool okv, ok;
  int numv, num, sz;
  Node() {
    okv = false;
    ok = true;
    numv = 0, num = 0, sz = 0;
  }
  template <class E>
  Node append_edge(int p, const E& e) const {
    Node n;
    n.okv = ok;
    n.ok = okv;
    n.numv = num;
    n.num = numv;
    n.sz = sz;
    return n;
  }
  Node operator+(const Node& r) const {
    Node n;
    n.okv = ok && r.okv || okv && r.ok;
    n.ok = ok && r.ok;
    n.numv = (r.okv ? num : 0) + (okv ? r.num : 0) + (r.ok ? numv : 0) +
             (ok ? r.numv : 0);
    n.num = (ok ? r.num : 0) + (r.ok ? num : 0);
    n.sz = sz + r.sz;
    return n;
  }
  void finalize(int r) {
    sz++;
    if (ok) numv++;
  }
};
struct Edge {
  int to;
};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(20);
  int N;
  cin >> N;
  VV<Edge> G(N);
  for (int i = 0; i < int(N - 1); i++) {
    int x, y;
    cin >> x >> y;
    x--, y--;
    G[x].push_back({y});
    G[y].push_back({x});
  }
  BidirectionalTreeDP<Node> dp(G);
  while (false) {
    int v, p;
    cin >> v >> p;
    auto d = dp.get(v, p);
    void(0);
    void(0);
    void(0);
    void(0);
  }
  ll ans = 0;
  for (int i = 0; i < int(N); i++) {
    for (auto e : G[i]) {
      int j = e.to;
      if (i < j) {
        auto x = dp.get(i, j);
        auto y = dp.get(j, i);
        void(0);
        void(0);
        void(0);
        void(0);
        void(0);
        void(0);
        void(0);
        void(0);
        void(0);
        ans += 1LL * x.numv * y.numv;
        if (x.okv && y.okv) ans += 1LL * x.sz * y.sz;
      }
    }
  }
  cout << ans << endl;
}
