import random
from collections import defaultdict
# Function to check if a node is a leaf node
def leaf(NODE, deg):
return deg[NODE] == 1 and NODE != 1
# DFS to calculate hash sum for subtree 1
def dfs1(curr, par, tree, subtree, deg, node):
for child in tree[curr]:
if child == par:
continue
dfs1(child, curr, tree, subtree, deg, node)
# If leaf node, hash sum is same as node's hash value
if leaf(curr, deg):
subtree[curr] = node[curr]
return
# Calculate hash sum of all children
sum_children = sum(subtree[child] for child in tree[curr])
subtree[curr] = node[curr] + sum_children
# Function to calculate hash sum for subtree 2
def dfs2(curr, par, tree, subtree, deg, node):
for child in tree[curr]:
if child == par:
continue
dfs2(child, curr, tree, subtree, deg, node)
# If leaf node, hash sum is same as node's hash value
if leaf(curr, deg):
subtree[curr] = node[curr]
return
# Calculate hash sum of all children
sum_children = sum(subtree[child] for child in tree[curr])
subtree[curr] = node[curr] + sum_children
# Calculates x^y in logN time
def exp(x, y):
if y == 0:
return 1
elif y & 1:
return x * exp(x, y // 2) * exp(x, y // 2)
else:
return exp(x, y // 2) * exp(x, y // 2)
# Helper function to build trees
def build_trees(tree1, tree2, deg1, deg2):
# Building Tree 1
edges_tree1 = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
for u, v in edges_tree1:
tree1[u].append(v)
tree1[v].append(u)
deg1[6] = 1 # 6 is a leaf node for tree 1
# Building Tree 2
edges_tree2 = [(1, 2), (2, 3), (1, 6), (6, 5), (5, 4)]
for u, v in edges_tree2:
tree2[u].append(v)
tree2[v].append(u)
deg2[3] = 1 # 3 is a leaf node for tree 2
deg2[4] = 1 # 4 is a leaf node for tree 2
# Function to assign random hash values to nodes
def assign_hash_values(n, node):
p = 97 * 13 * 19 # A very high prime
for i in range(1, n + 1):
val = (random.randint(0, 10000) * random.randint(0, 10000) * random.randint(0, 10000)) \
+ random.randint(0, 10000) * random.randint(0, 10000) + random.randint(0, 10000)
node[i] = val * p * random.randint(0, 10000) + p * 13 * 19 * random.randint(0, 10000) * random.randint(0, 10000) * 101 * p
p *= p
p *= p
# Function to solve the problem
def solve(n, tree1, tree2, subtree1, subtree2, deg1, deg2, node):
# Do DFS on both trees to get subtree[x] for each node
dfs1(1, 0, tree1, subtree1, deg1, node)
dfs2(1, 0, tree2, subtree2, deg2, node)
# Count hash values for each subtree of both trees
cnt_tree1 = defaultdict(int)
cnt_tree2 = defaultdict(int)
values = []
for i in range(1, n + 1):
value1 = subtree1[i]
value2 = subtree2[i]
values.append(value1)
cnt_tree1[value1] += 1
cnt_tree2[value2] += 1
# Stores the sum of all the hash values of children for root node of subtree 1.
root_tree1 = subtree1[1]
root_tree2 = subtree2[1]
cnt_tree1[root_tree1] = 0
cnt_tree2[root_tree2] = 0
# Count the number of equal hash values in both trees
answer = sum(1 for x in values if cnt_tree1[x] != 0 and cnt_tree2[x] != 0)
print(answer)
# Main function
def main():
n = 6
tree1 = [[] for _ in range(n + 1)]
tree2 = [[] for _ in range(n + 1)]
deg1 = [0] * (n + 1)
deg2 = [0] * (n + 1)
subtree1 = [0] * (n + 1)
subtree2 = [0] * (n + 1)
node = [0] * (n + 1)
# To generate a good random function
random.seed()
build_trees(tree1, tree2, deg1, deg2)
assign_hash_values(n, node)
solve(n, tree1, tree2, subtree1, subtree2, deg1, deg2, node)
if __name__ == "__main__":
main()