-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdsu.nim
51 lines (40 loc) · 1.05 KB
/
dsu.nim
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
import std/[
algorithm,
sequtils,
]
type DSU* = ref object
parent: seq[int]
rank: seq[int]
size: seq[int]
comps: int
proc newDSU*(n: int): DSU =
result.new
result.parent = (0 ..< n).toSeq
result.rank = newSeq[int](n)
result.size = newSeq[int](n)
result.size.fill 1
result.comps = n
proc append*(dsu: DSU): int =
result = dsu.parent.len
dsu.parent.add result
dsu.rank.add 0
dsu.size.add 1
dsu.comps.inc
proc find*(dsu: DSU, x: int): int =
if dsu.parent[x] != x: dsu.parent[x] = dsu.find(dsu.parent[x])
dsu.parent[x]
proc isConnected*(dsu: DSU, x: int, y: int): bool {.inline.} =
dsu.find(x) == dsu.find(y)
proc union*(dsu: DSU, x, y: int): bool {.discardable.} =
var (a, b) = (dsu.find(x), dsu.find(y))
if a == b: return false
if dsu.rank[a] < dsu.rank[b]: swap(a, b)
if dsu.rank[a] == dsu.rank[b]: dsu.rank[a].inc
dsu.parent[b] = a
dsu.size[a].inc dsu.size[b]
dsu.comps.dec
true
proc compSize*(dsu: DSU, x: int): int {.inline.} =
dsu.size[dsu.find(x)]
proc numComps*(dsu: DSU): int {.inline.} =
dsu.comps