-
Notifications
You must be signed in to change notification settings - Fork 31
/
有根树的同构.py
68 lines (55 loc) · 1.86 KB
/
有根树的同构.py
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
# https://judge.yosupo.jp/submission/102920
# rngハッシュ
# !每个点作为根节点时,求出树的哈希值,然后判断哈希值是否相同即可
# 只要求形态相同即可,不要求每个点的值也相同
from random import randint
from typing import List, Tuple
def rootedTreeIsomorphism(
n: int, edges: List[Tuple[int, int]], root=0, mod=(1 << 61) - 1
) -> List[int]:
tree = [[] for _ in range(n)]
for u, cur in edges:
tree[u].append(cur)
tree[cur].append(u)
parent = [-1] * n
height = [0] * n
order = [root]
stack = [root]
while stack:
cur = stack.pop()
for next in tree[cur]:
if parent[cur] == next:
continue
parent[next] = cur
order.append(next)
stack.append(next)
for i in range(len(order) - 1, 0, -1):
cur = order[i]
cand = height[cur] + 1
if cand > height[parent[cur]]:
height[parent[cur]] = cand
dp = [1] * n
rands = [randint(0, mod - 1) for _ in range(n)]
for i in range(len(order) - 1, -1, -1):
cur = order[i]
h = height[cur]
r = rands[h]
for next in tree[cur]:
if parent[cur] == next:
continue
dp[cur] *= r + dp[next]
dp[cur] %= mod
return dp
if __name__ == "__main__":
n = int(input())
parents = list(map(int, input().split()))
edges = []
for cur, pre in enumerate(parents):
edges.append((cur + 1, pre))
# 以每个根作为根节点求出树的哈希值
dp = rootedTreeIsomorphism(n, edges)
allNums = sorted(set(dp))
mp = {v: k for k, v in enumerate(allNums)}
res = [mp[h] for h in dp]
print(len(allNums)) # 哈希值的种类数
print(*res) # 每个根的哈希值的编号