@@ -26,6 +26,9 @@ assumed to be 1.
2626 # in which case we'll return immediately.
2727 (nvg > one (U)) || return (Vector {Int8} ([1 ]), zero (T))
2828
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
2932 is_merged = falses (nvg)
3033 merged_vertices = IntDisjointSets (U (nvg))
3134 graph_size = nvg
@@ -54,7 +57,6 @@ assumed to be 1.
5457
5558 is_processed = falses (nvg)
5659 @inbounds while graph_size > 1
57- cutweight = zero (T)
5860 is_processed .= false
5961 is_processed[u] = true
6062 # initialize pq
@@ -66,32 +68,23 @@ assumed to be 1.
6668 for v in fadjlist[u]
6769 (is_merged[v] || v == u) && continue
6870 pq[v] = w[u, v]
69- cutweight += w[u, v]
7071 end
7172 # Minimum cut phase
73+ local cutweight
7274 while true
7375 last_vertex = u
74- u, adj_cost = first (pq)
75- dequeue! (pq)
76+ u, cutweight = dequeue_pair! (pq)
7677 isempty (pq) && break
7778 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]
8881 end
8982 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
9285 # 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)
9588 graph_size -= 1
9689 end
9790 end
@@ -105,14 +98,14 @@ assumed to be 1.
10598 end
10699
107100 # 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)
109102 graph_size -= 1
110- u = root # we are sure this vertex was not merged, so the next phase start from it
111103 end
112104 return (convert (Vector{Int8}, parities) .+ one (Int8), bestweight)
113105end
114106
115107function _merge_vertex! (merged_vertices, fadjlist, is_merged, w, u, v)
108+ # root is kept, non-root is discarded
116109 root = union! (merged_vertices, u, v)
117110 non_root = (root == u) ? v : u
118111 is_merged[non_root] = true
@@ -122,7 +115,7 @@ function _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, v)
122115 w[v2, root] = w[root, v2]
123116 end
124117 # update neighbors
125- fadjlist[root] = union (fadjlist[root], fadjlist[non_root])
118+ union! (fadjlist[root], fadjlist[non_root])
126119 for v in fadjlist[non_root]
127120 if root ∉ fadjlist[v]
128121 push! (fadjlist[v], root)
0 commit comments