#include <bits/stdc++.h>
using namespace std;
inline char gc() {
  static char buf[1 << 14], *p1 = buf, *p2 = buf;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 14, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
inline long long read(long long &x) {
  x = 0;
  bool f = 1;
  char c = gc();
  for (; !isdigit(c); c = gc()) {
    if (c == '-') f ^= 1;
    if (c == -1) return -1;
  }
  for (; isdigit(c); c = gc()) x = (x << 1) + (x << 3) + (c ^ 48);
  x = f ? x : -x;
  return 1;
}
inline void wr(long long x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) wr(x / 10);
  putchar(x % 10 | 48);
}
const long long N = 1e5 + 10, P1 = 9376841, P2 = 998244353, P3 = 951299;
struct Ha {
  long long x, y;
  Ha(long long X = P3, long long Y = P3) : x(X), y(Y) {}
  bool operator<(const Ha &res) const {
    return x == res.x ? y < res.y : x < res.x;
  }
  Ha operator+(const Ha &res) const {
    return Ha((x + res.x) % P1, (y + res.y) % P2);
  }
  Ha operator*(const Ha &res) const {
    return Ha(x * res.x % P1, y * res.y % P2);
  }
};
struct edge {
  long long to, net;
} e[N << 1];
set<Ha> s;
map<long long, Ha> vis[N];
long long n, head[N], edge, ins[N];
inline void addedge(long long x, long long y) {
  e[++edge].to = y, e[edge].net = head[x], head[x] = edge;
  e[++edge].to = x, e[edge].net = head[y], head[y] = edge;
  ++ins[x], ++ins[y];
}
inline Ha dfs(long long x, long long fa) {
  if (vis[x].count(fa)) return vis[x][fa];
  Ha ret;
  for (long long i = head[x]; i; i = e[i].net)
    if (e[i].to != fa) {
      Ha t = dfs(e[i].to, x);
      ret = ret + t * t * t;
    }
  return vis[x][fa] = ret;
}
int main() {
  read(n);
  for (long long i = 1, x, y; i < n; ++i) read(x), read(y), addedge(x, y);
  for (long long i = 1; i <= n; ++i)
    if (ins[i] < 4) s.insert(dfs(i, 0));
  wr(s.size());
  return 0;
}
