mirror of
https://github.com/boostorg/graph.git
synced 2025-05-11 05:14:01 +00:00
Use reference arguments instead of pointers
This commit is contained in:
parent
dc9886b1cd
commit
6d9f2391b8
@ -474,9 +474,9 @@ struct maximum_weighted_matching_context
|
|||||||
|
|
||||||
/** Call a function for every vertex inside the specified blossom. */
|
/** Call a function for every vertex inside the specified blossom. */
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
static void for_vertices_in_blossom(const blossom_t* blossom, Func func)
|
static void for_vertices_in_blossom(const blossom_t& blossom, Func func)
|
||||||
{
|
{
|
||||||
auto ntb = blossom->nontrivial();
|
auto ntb = blossom.nontrivial();
|
||||||
if (ntb) {
|
if (ntb) {
|
||||||
// Visit all vertices in the non-trivial blossom.
|
// Visit all vertices in the non-trivial blossom.
|
||||||
// Use an explicit stack to avoid deep call chains.
|
// Use an explicit stack to avoid deep call chains.
|
||||||
@ -496,18 +496,18 @@ struct maximum_weighted_matching_context
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// A trivial blossom contains just one vertex.
|
// A trivial blossom contains just one vertex.
|
||||||
func(blossom->base_vertex);
|
func(blossom.base_vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Mark blossom as the top-level blossom of its vertices. */
|
/** Mark blossom as the top-level blossom of its vertices. */
|
||||||
void update_top_level_blossom(blossom_t* blossom)
|
void update_top_level_blossom(blossom_t& blossom)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!blossom->parent);
|
BOOST_ASSERT(!blossom.parent);
|
||||||
for_vertices_in_blossom(blossom,
|
for_vertices_in_blossom(blossom,
|
||||||
[this,blossom](vertex_t x)
|
[this,&blossom](vertex_t x)
|
||||||
{
|
{
|
||||||
vertex_top_blossom[x] = blossom;
|
vertex_top_blossom[x] = &blossom;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,26 +565,26 @@ struct maximum_weighted_matching_context
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Add edge between different S-blossoms. */
|
/** Add edge between different S-blossoms. */
|
||||||
void add_delta3_edge(blossom_t* b, const edge_t& e, weight_t slack)
|
void add_delta3_edge(blossom_t& b, const edge_t& e, weight_t slack)
|
||||||
{
|
{
|
||||||
auto& best_edge = b->best_edge;
|
auto& best_edge = b.best_edge;
|
||||||
if ((!best_edge.has_value()) || slack < edge_slack(*best_edge))
|
if ((!best_edge.has_value()) || slack < edge_slack(*best_edge))
|
||||||
best_edge = e;
|
best_edge = e;
|
||||||
|
|
||||||
auto ntb = b->nontrivial();
|
auto ntb = b.nontrivial();
|
||||||
if (ntb)
|
if (ntb)
|
||||||
ntb->best_edge_set.push_back(e);
|
ntb->best_edge_set.push_back(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update least-slack edge tracking after merging blossoms. */
|
/** Update least-slack edge tracking after merging blossoms. */
|
||||||
void merge_delta3_blossoms(nontrivial_blossom_t* blossom)
|
void merge_delta3_blossoms(nontrivial_blossom_t& blossom)
|
||||||
{
|
{
|
||||||
// Build a temporary array holding the least-slack edges to
|
// Build a temporary array holding the least-slack edges to
|
||||||
// other S-blossoms. The array is indexed by base vertex.
|
// other S-blossoms. The array is indexed by base vertex.
|
||||||
std::vector<least_slack_edge_t> tmp_best_edge(num_vertices(*g));
|
std::vector<least_slack_edge_t> tmp_best_edge(num_vertices(*g));
|
||||||
|
|
||||||
// Collect edges from sub-blossoms that were S-blossoms.
|
// Collect edges from sub-blossoms that were S-blossoms.
|
||||||
for (auto& sub : blossom->subblossoms)
|
for (auto& sub : blossom.subblossoms)
|
||||||
{
|
{
|
||||||
blossom_t* b = sub.blossom;
|
blossom_t* b = sub.blossom;
|
||||||
if (b->label == LABEL_S)
|
if (b->label == LABEL_S)
|
||||||
@ -598,7 +598,7 @@ struct maximum_weighted_matching_context
|
|||||||
{
|
{
|
||||||
blossom_t* bx = vertex_top_blossom[source(e, *g)];
|
blossom_t* bx = vertex_top_blossom[source(e, *g)];
|
||||||
blossom_t* by = vertex_top_blossom[target(e, *g)];
|
blossom_t* by = vertex_top_blossom[target(e, *g)];
|
||||||
BOOST_ASSERT(bx == blossom);
|
BOOST_ASSERT(bx == &blossom);
|
||||||
// Only use edges between top-level blossoms.
|
// Only use edges between top-level blossoms.
|
||||||
if (bx != by)
|
if (bx != by)
|
||||||
{
|
{
|
||||||
@ -621,7 +621,7 @@ struct maximum_weighted_matching_context
|
|||||||
blossom_t* by = vertex_top_blossom[y];
|
blossom_t* by = vertex_top_blossom[y];
|
||||||
// Only use edges to different S-blossoms.
|
// Only use edges to different S-blossoms.
|
||||||
// Ignore edges with negative weight.
|
// Ignore edges with negative weight.
|
||||||
if ((by != blossom)
|
if ((by != &blossom)
|
||||||
&& (by->label == LABEL_S)
|
&& (by->label == LABEL_S)
|
||||||
&& (get(edge_weights, e) >= 0))
|
&& (get(edge_weights, e) >= 0))
|
||||||
{
|
{
|
||||||
@ -635,18 +635,18 @@ struct maximum_weighted_matching_context
|
|||||||
|
|
||||||
// Build a compact list of edges from the temporary array.
|
// Build a compact list of edges from the temporary array.
|
||||||
// Also find the overall least-slack edge to any other S-blossom.
|
// Also find the overall least-slack edge to any other S-blossom.
|
||||||
BOOST_ASSERT(blossom->best_edge_set.empty());
|
BOOST_ASSERT(blossom.best_edge_set.empty());
|
||||||
BOOST_ASSERT(!blossom->best_edge.has_value());
|
BOOST_ASSERT(!blossom.best_edge.has_value());
|
||||||
least_slack_edge_t best_edge;
|
least_slack_edge_t best_edge;
|
||||||
for (const least_slack_edge_t& item : tmp_best_edge)
|
for (const least_slack_edge_t& item : tmp_best_edge)
|
||||||
{
|
{
|
||||||
if (item.edge.has_value())
|
if (item.edge.has_value())
|
||||||
{
|
{
|
||||||
blossom->best_edge_set.push_back(*item.edge);
|
blossom.best_edge_set.push_back(*item.edge);
|
||||||
best_edge.update(*item.edge, item.slack);
|
best_edge.update(*item.edge, item.slack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blossom->best_edge = best_edge.edge;
|
blossom.best_edge = best_edge.edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return least-slack edge between any pair of S-blossoms. */
|
/** Return least-slack edge between any pair of S-blossoms. */
|
||||||
@ -666,7 +666,7 @@ struct maximum_weighted_matching_context
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Add the vertices in a blossom to the scan queue. */
|
/** Add the vertices in a blossom to the scan queue. */
|
||||||
void add_vertices_to_scan_queue(blossom_t* blossom)
|
void add_vertices_to_scan_queue(blossom_t& blossom)
|
||||||
{
|
{
|
||||||
for_vertices_in_blossom(blossom,
|
for_vertices_in_blossom(blossom,
|
||||||
[this](vertex_t x)
|
[this](vertex_t x)
|
||||||
@ -736,16 +736,16 @@ struct maximum_weighted_matching_context
|
|||||||
|
|
||||||
// Create the new blossom.
|
// Create the new blossom.
|
||||||
nontrivial_blossom.emplace_back(subblossoms, path);
|
nontrivial_blossom.emplace_back(subblossoms, path);
|
||||||
nontrivial_blossom_t* blossom = &nontrivial_blossom.back();
|
nontrivial_blossom_t& blossom = nontrivial_blossom.back();
|
||||||
|
|
||||||
// Link the subblossoms to the new parent.
|
// Link the subblossoms to the new parent.
|
||||||
// Insert former T-vertices into the scan queue.
|
// Insert former T-vertices into the scan queue.
|
||||||
for (blossom_t* b : subblossoms)
|
for (blossom_t* b : subblossoms)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!b->parent);
|
BOOST_ASSERT(!b->parent);
|
||||||
b->parent = blossom;
|
b->parent = &blossom;
|
||||||
if (b->label == LABEL_T)
|
if (b->label == LABEL_T)
|
||||||
add_vertices_to_scan_queue(b);
|
add_vertices_to_scan_queue(*b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark vertices as belonging to the new blossom.
|
// Mark vertices as belonging to the new blossom.
|
||||||
@ -753,15 +753,15 @@ struct maximum_weighted_matching_context
|
|||||||
|
|
||||||
// Assign label S to the new blossom and link to the alternating tree.
|
// Assign label S to the new blossom and link to the alternating tree.
|
||||||
BOOST_ASSERT(subblossoms.front()->label == LABEL_S);
|
BOOST_ASSERT(subblossoms.front()->label == LABEL_S);
|
||||||
blossom->label = LABEL_S;
|
blossom.label = LABEL_S;
|
||||||
blossom->tree_edge = subblossoms.front()->tree_edge;
|
blossom.tree_edge = subblossoms.front()->tree_edge;
|
||||||
blossom->tree_root = subblossoms.front()->tree_root;
|
blossom.tree_root = subblossoms.front()->tree_root;
|
||||||
|
|
||||||
// Merge least-slack edges for the S-sub-blossoms.
|
// Merge least-slack edges for the S-sub-blossoms.
|
||||||
merge_delta3_blossoms(blossom);
|
merge_delta3_blossoms(blossom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Expand a T-blossom. */
|
/** Expand and delete a T-blossom. */
|
||||||
void expand_t_blossom(nontrivial_blossom_t* blossom)
|
void expand_t_blossom(nontrivial_blossom_t* blossom)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!blossom->parent);
|
BOOST_ASSERT(!blossom->parent);
|
||||||
@ -774,7 +774,7 @@ struct maximum_weighted_matching_context
|
|||||||
BOOST_ASSERT(b->parent == blossom);
|
BOOST_ASSERT(b->parent == blossom);
|
||||||
b->parent = nullptr;
|
b->parent = nullptr;
|
||||||
b->label = LABEL_NONE;
|
b->label = LABEL_NONE;
|
||||||
update_top_level_blossom(b);
|
update_top_level_blossom(*b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconstruct the alternating tree via the sub-blossoms.
|
// Reconstruct the alternating tree via the sub-blossoms.
|
||||||
@ -837,16 +837,16 @@ struct maximum_weighted_matching_context
|
|||||||
}
|
}
|
||||||
|
|
||||||
void augment_blossom_rec(
|
void augment_blossom_rec(
|
||||||
nontrivial_blossom_t* blossom, blossom_t* entry,
|
nontrivial_blossom_t& blossom, blossom_t& entry,
|
||||||
std::stack<std::pair<nontrivial_blossom_t*, blossom_t*>>& stack)
|
std::stack<std::pair<nontrivial_blossom_t*, blossom_t*>>& stack)
|
||||||
{
|
{
|
||||||
auto subblossom_loc = blossom->find_subblossom(entry);
|
auto subblossom_loc = blossom.find_subblossom(&entry);
|
||||||
auto entry_pos = subblossom_loc.first;
|
auto entry_pos = subblossom_loc.first;
|
||||||
auto entry_it = subblossom_loc.second;
|
auto entry_it = subblossom_loc.second;
|
||||||
|
|
||||||
// Walk from entry to the base in an even number of steps.
|
// Walk from entry to the base in an even number of steps.
|
||||||
auto sub_begin = blossom->subblossoms.begin();
|
auto sub_begin = blossom.subblossoms.begin();
|
||||||
auto sub_end = blossom->subblossoms.end();
|
auto sub_end = blossom.subblossoms.end();
|
||||||
auto sub_it = entry_it;
|
auto sub_it = entry_it;
|
||||||
while ((sub_it != sub_begin) && (sub_it != sub_end)) {
|
while ((sub_it != sub_begin) && (sub_it != sub_end)) {
|
||||||
vertex_t x, y;
|
vertex_t x, y;
|
||||||
@ -872,7 +872,7 @@ struct maximum_weighted_matching_context
|
|||||||
bx = sub_it->blossom;
|
bx = sub_it->blossom;
|
||||||
++sub_it;
|
++sub_it;
|
||||||
by = (sub_it == sub_end) ?
|
by = (sub_it == sub_end) ?
|
||||||
blossom->subblossoms.front().blossom :
|
blossom.subblossoms.front().blossom :
|
||||||
sub_it->blossom;
|
sub_it->blossom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,16 +892,16 @@ struct maximum_weighted_matching_context
|
|||||||
|
|
||||||
// Re-orient the blossom.
|
// Re-orient the blossom.
|
||||||
if (entry_it != sub_begin)
|
if (entry_it != sub_begin)
|
||||||
blossom->subblossoms.splice(
|
blossom.subblossoms.splice(
|
||||||
sub_begin, blossom->subblossoms, entry_it, sub_end);
|
sub_begin, blossom.subblossoms, entry_it, sub_end);
|
||||||
blossom->base_vertex = entry->base_vertex;
|
blossom.base_vertex = entry.base_vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void augment_blossom(nontrivial_blossom_t* blossom, blossom_t* entry)
|
void augment_blossom(nontrivial_blossom_t& blossom, blossom_t& entry)
|
||||||
{
|
{
|
||||||
// Use an explicit stack to avoid deep call chains.
|
// Use an explicit stack to avoid deep call chains.
|
||||||
std::stack<std::pair<nontrivial_blossom_t*, blossom_t*>> stack;
|
std::stack<std::pair<nontrivial_blossom_t*, blossom_t*>> stack;
|
||||||
stack.emplace(blossom, entry);
|
stack.emplace(&blossom, &entry);
|
||||||
|
|
||||||
while (!stack.empty()) {
|
while (!stack.empty()) {
|
||||||
nontrivial_blossom_t* outer_blossom;
|
nontrivial_blossom_t* outer_blossom;
|
||||||
@ -916,7 +916,7 @@ struct maximum_weighted_matching_context
|
|||||||
else
|
else
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
|
||||||
augment_blossom_rec(inner_blossom, inner_entry, stack);
|
augment_blossom_rec(*inner_blossom, *inner_entry, stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,12 +937,12 @@ struct maximum_weighted_matching_context
|
|||||||
blossom_t* bx = vertex_top_blossom[x];
|
blossom_t* bx = vertex_top_blossom[x];
|
||||||
auto bx_ntb = bx->nontrivial();
|
auto bx_ntb = bx->nontrivial();
|
||||||
if (bx_ntb)
|
if (bx_ntb)
|
||||||
augment_blossom(bx_ntb, &trivial_blossom[x]);
|
augment_blossom(*bx_ntb, trivial_blossom[x]);
|
||||||
|
|
||||||
blossom_t* by = vertex_top_blossom[y];
|
blossom_t* by = vertex_top_blossom[y];
|
||||||
auto by_ntb = by->nontrivial();
|
auto by_ntb = by->nontrivial();
|
||||||
if (by_ntb)
|
if (by_ntb)
|
||||||
augment_blossom(by_ntb, &trivial_blossom[y]);
|
augment_blossom(*by_ntb, trivial_blossom[y]);
|
||||||
|
|
||||||
// Pull this edge into the matching.
|
// Pull this edge into the matching.
|
||||||
vertex_mate[x] = y;
|
vertex_mate[x] = y;
|
||||||
@ -972,13 +972,13 @@ struct maximum_weighted_matching_context
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Remove edges to non-S-vertices from delta3 edge tracking. */
|
/** Remove edges to non-S-vertices from delta3 edge tracking. */
|
||||||
void refresh_delta3_blossom(blossom_t* b)
|
void refresh_delta3_blossom(blossom_t& b)
|
||||||
{
|
{
|
||||||
// Do nothing if this blossom was not tracking any delta3 edge.
|
// Do nothing if this blossom was not tracking any delta3 edge.
|
||||||
if (!b->best_edge.has_value())
|
if (!b.best_edge.has_value())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto ntb = b->nontrivial();
|
auto ntb = b.nontrivial();
|
||||||
if (ntb)
|
if (ntb)
|
||||||
{
|
{
|
||||||
// Remove bad edges from best_edge_set and refresh best_edge.
|
// Remove bad edges from best_edge_set and refresh best_edge.
|
||||||
@ -989,7 +989,7 @@ struct maximum_weighted_matching_context
|
|||||||
{
|
{
|
||||||
vertex_t y = target(*it, *g);
|
vertex_t y = target(*it, *g);
|
||||||
blossom_t* by = vertex_top_blossom[y];
|
blossom_t* by = vertex_top_blossom[y];
|
||||||
BOOST_ASSERT(by != b);
|
BOOST_ASSERT(by != &b);
|
||||||
if (by->label == LABEL_S)
|
if (by->label == LABEL_S)
|
||||||
{
|
{
|
||||||
best_edge.update(*it, edge_slack(*it));
|
best_edge.update(*it, edge_slack(*it));
|
||||||
@ -1001,16 +1001,16 @@ struct maximum_weighted_matching_context
|
|||||||
it = ntb->best_edge_set.erase(it);
|
it = ntb->best_edge_set.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b->best_edge = best_edge.edge;
|
b.best_edge = best_edge.edge;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Trivial blossom does not maintain best_edge_set.
|
// Trivial blossom does not maintain best_edge_set.
|
||||||
// If its current best_edge is invalid, recompute it.
|
// If its current best_edge is invalid, recompute it.
|
||||||
vertex_t x = b->base_vertex;
|
vertex_t x = b.base_vertex;
|
||||||
vertex_t y = target(*b->best_edge, *g);
|
vertex_t y = target(*b.best_edge, *g);
|
||||||
blossom_t* by = vertex_top_blossom[y];
|
blossom_t* by = vertex_top_blossom[y];
|
||||||
BOOST_ASSERT(by != b);
|
BOOST_ASSERT(by != &b);
|
||||||
if (by->label != LABEL_S)
|
if (by->label != LABEL_S)
|
||||||
{
|
{
|
||||||
// Consider all incident edges to recompute best_edge.
|
// Consider all incident edges to recompute best_edge.
|
||||||
@ -1020,10 +1020,10 @@ struct maximum_weighted_matching_context
|
|||||||
BOOST_ASSERT(source(e, *g) == x);
|
BOOST_ASSERT(source(e, *g) == x);
|
||||||
y = target(e, *g);
|
y = target(e, *g);
|
||||||
by = vertex_top_blossom[y];
|
by = vertex_top_blossom[y];
|
||||||
if ((by != b) && (by->label == LABEL_S))
|
if ((by != &b) && (by->label == LABEL_S))
|
||||||
best_edge.update(e, edge_slack(e));
|
best_edge.update(e, edge_slack(e));
|
||||||
}
|
}
|
||||||
b->best_edge = best_edge.edge;
|
b.best_edge = best_edge.edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1078,7 +1078,7 @@ struct maximum_weighted_matching_context
|
|||||||
ntb->best_edge_set.clear();
|
ntb->best_edge_set.clear();
|
||||||
|
|
||||||
// Visit edges that touch this blossom.
|
// Visit edges that touch this blossom.
|
||||||
for_vertices_in_blossom(b,
|
for_vertices_in_blossom(*b,
|
||||||
[&](vertex_t x)
|
[&](vertex_t x)
|
||||||
{
|
{
|
||||||
// Mark former S-vertices.
|
// Mark former S-vertices.
|
||||||
@ -1110,7 +1110,7 @@ struct maximum_weighted_matching_context
|
|||||||
for (vertex_t x : make_iterator_range(vertices(*g)))
|
for (vertex_t x : make_iterator_range(vertices(*g)))
|
||||||
{
|
{
|
||||||
if (blossom_recompute_best_edge[x])
|
if (blossom_recompute_best_edge[x])
|
||||||
refresh_delta3_blossom(vertex_top_blossom[x]);
|
refresh_delta3_blossom(*vertex_top_blossom[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recompute vertex_best_edge of affected non-S-vertices.
|
// Recompute vertex_best_edge of affected non-S-vertices.
|
||||||
@ -1151,7 +1151,7 @@ struct maximum_weighted_matching_context
|
|||||||
bz->label = LABEL_S;
|
bz->label = LABEL_S;
|
||||||
bz->tree_edge = std::make_pair(y2, z);
|
bz->tree_edge = std::make_pair(y2, z);
|
||||||
bz->tree_root = by->tree_root;
|
bz->tree_root = by->tree_root;
|
||||||
add_vertices_to_scan_queue(bz);
|
add_vertices_to_scan_queue(*bz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1243,7 +1243,7 @@ struct maximum_weighted_matching_context
|
|||||||
{
|
{
|
||||||
// Track non-tight edges between S-blossoms.
|
// Track non-tight edges between S-blossoms.
|
||||||
if (by->label == LABEL_S)
|
if (by->label == LABEL_S)
|
||||||
add_delta3_edge(bx, e, slack);
|
add_delta3_edge(*bx, e, slack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track all edges between S-blossom and non-S-blossom.
|
// Track all edges between S-blossom and non-S-blossom.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user