1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
static string encode_rooted(int u, int parent, const vector<vector<int>>& adj) {
vector<string> childCodes;
childCodes.reserve(adj[u].size());
for (int v : adj[u]) {
if (v == parent) continue;
childCodes.push_back(encode_rooted(v, u, adj));
}
sort(childCodes.begin(), childCodes.end());
string res = "(";
for (const string& s : childCodes) res += s;
res += ")";
return res;
}
static vector<int> find_centers(const vector<vector<int>>& adj) {
int n = (int)adj.size();
if (n == 1) return {0};
vector<int> degree(n);
queue<int> q;
for (int i = 0; i < n; ++i) {
degree[i] = (int)adj[i].size();
if (degree[i] == 1) q.push(i);
}
int remaining = n;
while (remaining > 2) {
int sz = (int)q.size();
remaining -= sz;
while (sz--) {
int u = q.front(); q.pop();
degree[u] = 0;
for (int v : adj[u]) {
if (degree[v] > 0) {
if (--degree[v] == 1) q.push(v);
}
}
}
}
vector<int> centers;
for (int i = 0; i < n; ++i) if (degree[i] > 0) centers.push_back(i);
if (centers.empty()) centers.push_back(q.front());
return centers;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
if (!(cin >> n)) return 0;
unordered_set<string> shapes;
shapes.reserve((size_t)min(1000000, n) * 2);
for (int i = 0; i < n; ++i) {
int s; cin >> s;
vector<vector<int>> adj(s);
for (int e = 0; e < s - 1; ++e) {
int u, v; cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
vector<int> centers = find_centers(adj);
if (centers.size() == 1) {
string code = encode_rooted(centers[0], -1, adj);
shapes.insert(move(code));
} else {
string a = encode_rooted(centers[0], -1, adj);
string b = encode_rooted(centers[1], -1, adj);
if (a < b) shapes.insert(move(a));
else shapes.insert(move(b));
}
}
cout << shapes.size() << '\n';
return 0;
}
|