#include #include //小数点出力用 //cout << fixed << setprecision(10) << ans; #include #include #include #include #include #include #include #include using ll = long long; using namespace std; #define modPHash (ll)((1LL<<61)-1) #define modP (ll)998244353 bool chkrng0idx(int pos, int sup) { return (0 <= pos && pos < sup); } int clk4(int num) { return (num - 2) * (num % 2); } void yn(bool tf) { cout << (tf ? "YES\n" : "NO\n"); } vector nxt[200002];//行先,距離 vector centroid_cand; int search_center(int now, int parent, int size) {//与えられた部分木内の重心を見つける 変更非推奨 int res = 1; bool ok = 1; for (int j = 0;j < nxt[now].size();j++) { if (parent != nxt[now][j]) { auto X = search_center(nxt[now][j], now, size); if (X > size / 2) { ok = 0; } res += X; } } if (size - res > size / 2) { ok = 0; } if (ok) { centroid_cand.push_back(now); } return res; } ll mul(ll X, ll Y) { ll res = 0; for (int k = 62;k >= 0;k--) { res <<= 1; res %= modPHash; if ((Y >> k) & 1) { res += X; res %= modPHash; } } return res; } ll getHash(int now, int parent) { vectorkid; kid.reserve(nxt[now].size()); ll res = 123456789; ll T = 1; for (int j = 0;j < nxt[now].size();j++) { if (parent != nxt[now][j]) { kid.push_back(getHash(nxt[now][j], now)); } } sort(kid.begin(), kid.end()); for (int j = 0;j < kid.size();j++) { res += mul(T, kid[j]); res %= modPHash; } return res; } ll kidCnt[100001]; ll underPair[100001]; ll underKind[100001]; ll dfs(int now, int parent) { vector>kid; kid.reserve(nxt[now].size()); ll res = 123456789; ll T = 1; for (int j = 0;j < nxt[now].size();j++) { if (parent != nxt[now][j]) { kid.push_back({ dfs(nxt[now][j], now), nxt[now][j] }); } } sort(kid.begin(), kid.end()); ll combo = 0; ll nowH = 0; int k = 0; underKind[now] = 1; underPair[now] = 1; ll backKind = 0; for (int j = 0;j < kid.size();j++) { res += mul(T, kid[j].first); res %= modPHash; if (nowH == kid[j].first) { combo++; } else { if (combo >= 2) { underPair[now] += underPair[k]; underPair[now] += 2LL * underKind[k]; underPair[now] += underKind[k] * underKind[k]; underKind[now] += underKind[k]; underPair[now] += backKind * underKind[k] * 2LL; backKind += underKind[k]; } if (combo == 1) { underPair[now] += underPair[k]; underPair[now] += 2LL * underKind[k]; underKind[now] += underKind[k]; underPair[now] += backKind * underKind[k] * 2LL; backKind += underKind[k]; } combo = 1; nowH = kid[j].first; k = kid[j].second; } T *= 3LL; T %= modPHash; } if (combo >= 2) { underPair[now] += underPair[k]; underPair[now] += 2LL * underKind[k]; underPair[now] += underKind[k] * underKind[k]; underKind[now] += underKind[k]; underPair[now] += backKind * underKind[k] * 2LL; } if (combo == 1) { underPair[now] += underPair[k]; underPair[now] += 2LL * underKind[k]; underKind[now] += underKind[k]; underPair[now] += backKind * underKind[k] * 2LL; } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; for (int i = 1;i < N;i++) { int U, V; cin >> U >> V; nxt[U].push_back(V); nxt[V].push_back(U); } if (N == 1) { cout << 1; return 0; } if (N == 2) { cout << 2; return 0; } if (N == 3) { cout << 5; return 0; } search_center(1, -1, N); if (centroid_cand.size() == 2 && getHash(centroid_cand[0], centroid_cand[1]) == getHash(centroid_cand[1], centroid_cand[0])) { dfs(centroid_cand[0], centroid_cand[1]); cout << underPair[centroid_cand[0]] + underKind[centroid_cand[0]] * underKind[centroid_cand[0]]; } else { dfs(centroid_cand[0], -1); cout << underPair[centroid_cand[0]]; } return 0; }