#include <bits/stdc++.h>   constexpr unsigned primes[]{2672090437, 2569161337, 2414657393};   constexpr int np = sizeof(primes) / sizeof(*primes);   std::vector<std::array<unsigned, np> > pow2;   void setpow2(int maxp) {     pow2.resize(maxp + 1);     for (int i = 0; i < np; i++) pow2[0][i] = 1;     for (int i = 1; i <= maxp; i++)       for (int j = 0; j < np; j++) pow2[i][j] = pow2[i - 1][j] * 2ULL % primes[j];   }   struct hash {     unsigned m[np];     int nbits;     hash() {}     hash(unsigned num, int nbits = 1) : nbits(nbits) {       for (int i = 0; i < np; i++) m[i] = num;     }   };   hash join(hash a, hash b) {     hash out;     out.nbits = a.nbits + b.nbits;     for (int i = 0; i < np; i++)       out.m[i] = (a.m[i] * (uint64_t)pow2[b.nbits][i] + b.m[i]) % primes[i];     return out;   }   bool operator<(hash a, hash b) {     if (a.nbits != b.nbits) return a.nbits < b.nbits;     return memcmp(a.m, b.m, sizeof(a.m)) < 0;   }   int w[100000];   std::vector<int> adj[100000];   hash h0[100000];   hash hnew[100000];   int deg[100000];   int findw(int v, int par = -1) {     int t = 1;     for (int x : adj[v]) {       if (x != par) t += findw(x, v);     }     return w[v] = t;   }   void genh0(int v, bool rec = true) {     if (rec) {       for (int x : adj[v]) genh0(x);     }     std::sort(adj[v].begin(), adj[v].end(),               [](int a, int b) { return h0[a] < h0[b]; });     hash out(0);     for (int x : adj[v]) out = join(out, h0[x]);     h0[v] = join(out, hash(1));   }   void hconcat(int v, hash h) {     hnew[v] = memcmp(hnew[v].m, h.m, sizeof(h.m)) < 0 ? join(hnew[v], h)                                                       : join(h, hnew[v]);     for (int x : adj[v]) hconcat(x, h);   }   int main() {     std::ios_base::sync_with_stdio(false);     int n;     scanf( %d , &n);     setpow2(2 * n + 5);     for (int i = n; --i;) {       int a, b;       scanf( %d %d , &a, &b);       --a;       --b;       adj[a].push_back(b);       adj[b].push_back(a);       ++deg[a];       ++deg[b];     }     findw(0);     std::vector<int> center;     for (int i = n; i--;) {       if (n % 2 == 0 && w[i] == n / 2) {         for (int j : adj[i]) {           if (w[j] > w[i]) {             center = {i, j};             break;           }         }         break;       } else if (n - w[i] < (n + 1) / 2) {         bool isC = true;         for (int v : adj[i]) isC &= w[v] > w[i] || w[v] < (n + 1) / 2;         if (isC) {           center = {i};           break;         }       }     }     bool ecent = center.size() == 2;     for (auto i = center.size(); i--;) findw(center[i], center[i ^ +ecent]);     for (int i = n; i--;) {       std::sort(adj[i].begin(), adj[i].end(),                 [](int a, int b) { return w[a] < w[b]; });       if (n > 1 && (ecent || i != center[0])) adj[i].pop_back();     }     struct split {       const int *eqb, *eqe;       hash pre, post;     };     std::vector<split> ss;     const hash h01 = join(hash(0), hash(1));     std::function<void(int, hash, hash, int)> genh;     int nbad = 0;     genh = [&](int v, hash pre, hash post, int skipw) {       if (deg[v] < 4) {         hash h = join(pre, h01);         for (int x : adj[v]) h = join(h, h0[x]);         h = join(h, post);         for (auto it = ss.crbegin(); it != ss.crend(); ++it) {           hash hh = it->pre;           bool inserted = false;           for (const int* i = it->eqb; i != it->eqe; ++i) {             if (!inserted && memcmp(h.m, h0[*i].m, sizeof(h.m)) < 0) {               inserted = true;               hh = join(hh, h);             }             hh = join(hh, h0[*i]);           }           if (!inserted) hh = join(hh, h);           h = join(hh, it->post);         }         hnew[v] = h;       } else {         hnew[v].nbits = -1;         nbad++;       }       for (auto aj = adj[v].cbegin(), ae = adj[v].cend(); aj != ae; ++aj) {         if (w[*aj] == skipw) continue;         auto a2 = aj;         do ++a2;         while (a2 != ae && w[*a2] == w[*aj]);         hash pre2 = pre, post2 = post;         for (auto a = adj[v].cbegin(); a != a2; ++a) {           if (a != aj) pre2 = join(pre2, h0[*a]);         }         if (a2 != ae && w[*a2] == w[*aj] + 1) {           auto a3 = a2;           do ++a3;           while (a3 != ae && w[*a3] == w[*a2]);           for (auto a = ae; a != a3;) post2 = join(h0[*--a], post2);           ss.push_back(split{&*a2, &*a2 + (a3 - a2), pre2, post2});           genh(*aj, hash(0), hash(1), -1);           ss.pop_back();         } else {           for (auto a = ae; a != a2;) post2 = join(h0[*--a], post2);           pre2 = join(pre2, hash(0));           post2 = join(hash(1), post2);           genh(*aj, pre2, post2, -1);         }       }     };     if (ecent) {       genh0(center[0]);       genh0(center[1]);       for (int i : {0, 1}) {         int c = center[i];         adj[c].push_back(center[i ^ 1]);         genh(c, hash(0, 0), hash(0, 0), n / 2);         adj[c].pop_back();       }     } else {       int c = center[0];       genh0(c);       genh(c, hash(0, 0), hash(0, 0), n / 2);       for (auto i = adj[c].size(); i--;) {         int c2 = adj[c][i];         if (w[c2] != n / 2) continue;         adj[c].erase(adj[c].begin() + i);         genh0(c, false);         genh(c2, hash(0, 0), hash(0, 0), -1);         adj[c].insert(adj[c].begin() + i, c2);         hconcat(c2, h0[c]);       }     }     std::sort(hnew, hnew + n);     int ans = 1;     for (int i = nbad + 1; i < n; i++) {       if (memcmp(hnew + i, hnew + i - 1, sizeof(*hnew))) ++ans;     }     std::cout << ans;     return 0;   }