-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathresisting_robots.py3
67 lines (62 loc) · 2.19 KB
/
resisting_robots.py3
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
# Copyright (c) 2023 kamyu. All rights reserved.
#
# Meta Hacker Cup 2023 Final Round - Problem C. Resisting Robots
# https://www.facebook.com/codingcompetitions/hacker-cup/2023/final-round/problems/C
#
# Time: O(NlogN + M)
# Space: O(N + M)
#
def resisting_robots():
class UnionFind(object): # Time: O(n * alpha(n)), Space: O(n)
def __init__(self, arr): # modified
self.set = list(range(len(arr)))
self.ranks = [0]*len(arr)
self.last = list(range(len(arr))) # added
self.total = arr[:] # added
self.p = [-1]*len(arr) # added
def find_set(self, x):
stk = []
while self.set[x] != x: # path compression
stk.append(x)
x = self.set[x]
while stk:
self.set[stk.pop()] = x
return x
def union_set(self, x, y):
x, y = self.find_set(x), self.find_set(y)
if x == y:
return False
prev_x, prev_y = self.last[x], self.last[y] # added
if self.ranks[x] > self.ranks[y]: # union by ranks
x, y = y, x
self.set[x] = self.set[y]
if self.ranks[x] == self.ranks[y]:
self.ranks[y] += 1
self.last[y] = prev_x # added
self.total[prev_x] += self.total[prev_y] # added
self.p[prev_y] = prev_x # added
return True
N, M = list(map(int, input().split()))
P = list(map(int, input().split()))
A_B = [list(map(lambda x: int(x)-1, input().split())) for _ in range(M)]
idxs = list(range(N))
idxs.sort(key=lambda x: P[x])
ranks = [0]*N
for i, x in enumerate(idxs):
ranks[x] = i
adj = [[] for _ in range(N)]
for u, v in A_B:
if ranks[u] < ranks[v]:
u, v = v, u
adj[u].append(v)
uf = UnionFind(P)
for u in idxs:
for v in adj[u]:
uf.union_set(u, v)
result = [float("inf")]*N
for u in reversed(idxs):
v = uf.p[u]
result[u] = max(result[v], P[v]-uf.total[u]) if v != -1 else 0
return sum(result)
for case in range(int(input())):
print('Case #%d: %s' % (case+1, resisting_robots()))