@@ -26,6 +26,9 @@ assumed to be 1.
26
26
# in which case we'll return immediately.
27
27
(nvg > one (U)) || return (Vector {Int8} ([1 ]), zero (T))
28
28
29
+ # to avoid reallocating lists in fadjlist, we have some already merged vertices
30
+ # still appearing in fadjlist. When iterating neighbors, is_merged makes sure we
31
+ # don't consider them
29
32
is_merged = falses (nvg)
30
33
merged_vertices = IntDisjointSets (U (nvg))
31
34
graph_size = nvg
@@ -54,7 +57,6 @@ assumed to be 1.
54
57
55
58
is_processed = falses (nvg)
56
59
@inbounds while graph_size > 1
57
- cutweight = zero (T)
58
60
is_processed .= false
59
61
is_processed[u] = true
60
62
# initialize pq
@@ -66,32 +68,23 @@ assumed to be 1.
66
68
for v in fadjlist[u]
67
69
(is_merged[v] || v == u) && continue
68
70
pq[v] = w[u, v]
69
- cutweight += w[u, v]
70
71
end
71
72
# Minimum cut phase
73
+ local cutweight
72
74
while true
73
75
last_vertex = u
74
- u, adj_cost = first (pq)
75
- dequeue! (pq)
76
+ u, cutweight = dequeue_pair! (pq)
76
77
isempty (pq) && break
77
78
for v in fadjlist[u]
78
- (is_merged[v] || u == v) && continue
79
- # if the target of e is already marked then decrease cutweight
80
- # otherwise, increase it
81
- ew = w[u, v]
82
- if is_processed[v]
83
- cutweight -= ew
84
- else
85
- cutweight += ew
86
- pq[v] += ew
87
- end
79
+ (is_processed[v] || is_merged[v] || u == v) && continue
80
+ pq[v] += w[u, v]
88
81
end
89
82
is_processed[u] = true
90
- # adj_cost is a lower bound on the cut separating the two last vertices
91
- # encountered, so if adj_cost >= bestweight, we can already merge these
83
+ # cutweight is a lower bound on the cut separating the two last vertices
84
+ # encountered, so if cutweight >= bestweight, we can already merge these
92
85
# vertices to save one phase.
93
- if adj_cost >= bestweight
94
- _merge_vertex! (merged_vertices, fadjlist, is_merged, w, u, last_vertex)
86
+ if cutweight >= bestweight
87
+ u = _merge_vertex! (merged_vertices, fadjlist, is_merged, w, u, last_vertex)
95
88
graph_size -= 1
96
89
end
97
90
end
@@ -105,14 +98,14 @@ assumed to be 1.
105
98
end
106
99
107
100
# merge u and last_vertex
108
- root = _merge_vertex! (merged_vertices, fadjlist, is_merged, w, u, last_vertex)
101
+ u = _merge_vertex! (merged_vertices, fadjlist, is_merged, w, u, last_vertex)
109
102
graph_size -= 1
110
- u = root # we are sure this vertex was not merged, so the next phase start from it
111
103
end
112
104
return (convert (Vector{Int8}, parities) .+ one (Int8), bestweight)
113
105
end
114
106
115
107
function _merge_vertex! (merged_vertices, fadjlist, is_merged, w, u, v)
108
+ # root is kept, non-root is discarded
116
109
root = union! (merged_vertices, u, v)
117
110
non_root = (root == u) ? v : u
118
111
is_merged[non_root] = true
@@ -122,7 +115,7 @@ function _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, v)
122
115
w[v2, root] = w[root, v2]
123
116
end
124
117
# update neighbors
125
- fadjlist[root] = union (fadjlist[root], fadjlist[non_root])
118
+ union! (fadjlist[root], fadjlist[non_root])
126
119
for v in fadjlist[non_root]
127
120
if root ∉ fadjlist[v]
128
121
push! (fadjlist[v], root)
0 commit comments