-
Notifications
You must be signed in to change notification settings - Fork 2
/
Tree isomorphism (non rooted).cpp
61 lines (49 loc) · 1.09 KB
/
Tree isomorphism (non rooted).cpp
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
/*8<
@Title:
Tree Isomorphism (not rooted)
@Description:
Two trees are considered \textbf{isomorphic}
if the hash given by $thash()$ is the same.
@Time:
$O(V \cdot \log{V})$
>8*/
map<vi, int> mphash;
struct Tree {
int n;
vi2d g;
vi sz, cs;
Tree(int n_) : n(n_), g(n), sz(n) {}
void add_edge(int u, int v) {
g[u].emplace_back(v);
g[v].emplace_back(u);
}
void dfs_centroid(int v, int p) {
sz[v] = 1;
bool cent = true;
for (int u : g[v])
if (u != p) {
dfs_centroid(u, v);
sz[v] += sz[u];
cent &= not(sz[u] > n / 2);
}
if (cent and n - sz[v] <= n / 2)
cs.push_back(v);
}
int fhash(int v, int p) {
vi h;
for (int u : g[v])
if (u != p) h.push_back(fhash(u, v));
sort(all(h));
if (!mphash.count(h))
mphash[h] = mphash.size();
return mphash[h];
}
ll thash() {
cs.clear();
dfs_centroid(0, -1);
if (cs.size() == 1) return fhash(cs[0], -1);
ll h1 = fhash(cs[0], cs[1]),
h2 = fhash(cs[1], cs[0]);
return (min(h1, h2) << 30ll) + max(h1, h2);
}
};