from math import lcm, gcd
n = int(input())
graph = []
original_degs = []
froms = [[] for _ in range(n)]
for i in range(n):
line = [i - 1 for i in map(int, input().split())]
original_degs.append(line[0] + 1)
graph.append(line[1:])
for neigh in line[1:]:
froms[neigh].append(i)
reachable = [False for _ in range(n)]
nodes = [0]
reachable[0] = True
while nodes:
node = nodes.pop()
for v in graph[node]:
if not reachable[v]:
reachable[v] = True
nodes.append(v)
# print(graph)
topo = []
degs = original_degs[:]
bag = list(filter(lambda i: reachable[i] and (degs[i] == 0), range(n)))
while bag:
v = bag.pop()
topo.append(v)
for neigh in froms[v]:
if not reachable[neigh]:
continue
degs[neigh] -= 1
if not degs[neigh]:
bag.append(neigh)
def calc():
vals = [0 for _ in range(n)]
for v in topo:
# print(f'calc for {v}')
if not len(graph[v]):
# print('no children')
vals[v] = 1
else:
# print(f'{len(graph[v])} children')
vals[v] = len(graph[v]) * lcm(*[vals[w] for w in graph[v]])
# print(f'val is {vals[v]}')
return vals
def push(vals, moves):
to_move = [0 for _ in range(n)]
to_move[0] = moves
for v in range(n):
vals[v] = to_move[v]
# print(f'{v} moving {vals[v]} times')
if not graph[v]:
continue
sub_moves = vals[v] // len(graph[v])
for neigh in graph[v]:
# print(f'{neigh} gets additional {sub_moves} from {v}')
to_move[neigh] += sub_moves
def ok(times):
# print(f'times: {times}')
# print(f'vals: {vals}')
status = [
not reachable[i]
or
(
times[i]
and
(
not graph[i]
or
not (times[i] % len(graph[i]))
)
) for i in range(n)
]
# print(f'status: {status}')
return all(
status
)
# print(ret)
# return ret
vals = calc()
# print(f'vals: {vals}')
# top_prime = 105
# notprimes = set(j for i in range(2, top_prime) for j in range(2 * i, top_prime, i))
# primes = [x for x in range(2, top_prime) if x not in notprimes]
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103]
# print(primes)
ans = vals[0]
# print(ans)
# times = [0 for _ in range(n)]
# push(times, ans)
# if not ok(times):
# raise RuntimeError()
for prime in primes:
if (prime > ans) or (ans % prime):
continue
while True:
nans = ans // prime
# print(f'checking {nans}')
times = [0 for _ in range(n)]
push(times, nans)
if not ok(times):
break
# print(f'{nans} becomes ans')
ans = nans
print(ans)
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | from math import lcm, gcd n = int(input()) graph = [] original_degs = [] froms = [[] for _ in range(n)] for i in range(n): line = [i - 1 for i in map(int, input().split())] original_degs.append(line[0] + 1) graph.append(line[1:]) for neigh in line[1:]: froms[neigh].append(i) reachable = [False for _ in range(n)] nodes = [0] reachable[0] = True while nodes: node = nodes.pop() for v in graph[node]: if not reachable[v]: reachable[v] = True nodes.append(v) # print(graph) topo = [] degs = original_degs[:] bag = list(filter(lambda i: reachable[i] and (degs[i] == 0), range(n))) while bag: v = bag.pop() topo.append(v) for neigh in froms[v]: if not reachable[neigh]: continue degs[neigh] -= 1 if not degs[neigh]: bag.append(neigh) def calc(): vals = [0 for _ in range(n)] for v in topo: # print(f'calc for {v}') if not len(graph[v]): # print('no children') vals[v] = 1 else: # print(f'{len(graph[v])} children') vals[v] = len(graph[v]) * lcm(*[vals[w] for w in graph[v]]) # print(f'val is {vals[v]}') return vals def push(vals, moves): to_move = [0 for _ in range(n)] to_move[0] = moves for v in range(n): vals[v] = to_move[v] # print(f'{v} moving {vals[v]} times') if not graph[v]: continue sub_moves = vals[v] // len(graph[v]) for neigh in graph[v]: # print(f'{neigh} gets additional {sub_moves} from {v}') to_move[neigh] += sub_moves def ok(times): # print(f'times: {times}') # print(f'vals: {vals}') status = [ not reachable[i] or ( times[i] and ( not graph[i] or not (times[i] % len(graph[i])) ) ) for i in range(n) ] # print(f'status: {status}') return all( status ) # print(ret) # return ret vals = calc() # print(f'vals: {vals}') # top_prime = 105 # notprimes = set(j for i in range(2, top_prime) for j in range(2 * i, top_prime, i)) # primes = [x for x in range(2, top_prime) if x not in notprimes] primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103] # print(primes) ans = vals[0] # print(ans) # times = [0 for _ in range(n)] # push(times, ans) # if not ok(times): # raise RuntimeError() for prime in primes: if (prime > ans) or (ans % prime): continue while True: nans = ans // prime # print(f'checking {nans}') times = [0 for _ in range(n)] push(times, nans) if not ok(times): break # print(f'{nans} becomes ans') ans = nans print(ans) |
English