-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdsu.ml
71 lines (58 loc) · 1.71 KB
/
dsu.ml
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
module type S = sig
type t
type elt
val empty : unit -> t
val repr : t -> elt -> elt
val unite : t -> elt -> elt -> unit
val mem : t -> elt -> bool
val eles : t -> elt Seq.t
val all_repr : t -> elt Seq.t
val set_rank : t -> elt -> int -> unit
end
module Make (E : Hashtbl.HashedType) = struct
module PH = Hashtbl.Make (E)
type t = {
par : E.t PH.t;
rank : (int*int) PH.t
}
type elt = E.t
let empty () =
{par = PH.create 100; rank = PH.create 100}
let rec repr dsu x =
match PH.find_opt dsu.par x with
| None ->
PH.(replace dsu.par x x; replace dsu.rank x (0,1); x)
| Some y -> if not (E.equal x y) then repr dsu y else x
let unite dsu x y =
let open PH in
if E.equal x y then () else begin
let x = repr dsu x in
let y = repr dsu y in
let rankx = find dsu.rank x in
let ranky = find dsu.rank y in
let rank' =
(max (fst rankx) (fst ranky),(snd rankx)+(snd ranky))
in
if ranky > rankx then
(replace dsu.par x y; replace dsu.rank y rank')
else
(replace dsu.par y x; replace dsu.rank x rank')
end
let mem dsu = PH.mem dsu.rank
let eles dsu = PH.to_seq_keys dsu.rank
let all_repr dsu =
Seq.filter (fun x -> E.equal x (repr dsu x)) @@ eles dsu
let set_rank dsu x r =
let xp = repr dsu x in
if E.equal x xp then () else begin
let rx = PH.find dsu.rank x in
let rxp = PH.find dsu.rank xp in
let rxp' = (fst rxp, (snd rxp)-(snd rx)) in
PH.replace dsu.rank xp rxp';
PH.replace dsu.rank x (r, snd rx);
PH.replace dsu.par x x;
unite dsu xp x;
(* assert (E.equal (repr dsu x) x);
assert (E.equal (repr dsu xp) x) *)
end
end