ensure all outer vertices are scanned
This commit is contained in:
parent
14474189c4
commit
1b9f930adf
1 changed files with 89 additions and 77 deletions
166
src/edmonds.cpp
166
src/edmonds.cpp
|
@ -30,101 +30,113 @@ std::vector<NodeId> path_to_forest_root(Graph const & graph, NodeId id)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeId find_outer_vertex(Graph const & graph)
|
||||||
|
{
|
||||||
|
for(NodeId id = 0; id < graph.num_nodes(); ++id)
|
||||||
|
{
|
||||||
|
if (not graph.node(id).scanned and graph.is_outer(id))
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return invalid_node_id;
|
||||||
|
}
|
||||||
|
|
||||||
Graph maximum_matching_from_initial_matching(Graph & graph)
|
Graph maximum_matching_from_initial_matching(Graph & graph)
|
||||||
{
|
{
|
||||||
graph.reset_forest();
|
graph.reset_forest();
|
||||||
for(NodeId id = 0; id < graph.num_nodes(); ++id) {
|
NodeId id;
|
||||||
if (graph.is_outer(id))
|
while((id = find_outer_vertex(graph)) != invalid_node_id)
|
||||||
|
{
|
||||||
|
for(NodeId neighbor_id : graph.node(id).neighbors())
|
||||||
{
|
{
|
||||||
for(NodeId neighbor_id : graph.node(id).neighbors())
|
if (graph.is_out_of_forest(neighbor_id))
|
||||||
{
|
{
|
||||||
if (graph.is_out_of_forest(neighbor_id))
|
// Grow Forest
|
||||||
{
|
graph.node(neighbor_id).ear_or_root_neighbor = id;
|
||||||
// Grow Forest
|
}
|
||||||
graph.node(neighbor_id).ear_or_root_neighbor = id;
|
else if (graph.is_outer(neighbor_id) and \
|
||||||
}
|
graph.root_of_ear_component(id) != graph.root_of_ear_component(neighbor_id))
|
||||||
else if (graph.is_outer(neighbor_id) and \
|
{
|
||||||
graph.root_of_ear_component(id) != graph.root_of_ear_component(neighbor_id))
|
std::vector<NodeId> x_path = path_to_forest_root(graph, id);
|
||||||
{
|
std::vector<NodeId> y_path = path_to_forest_root(graph, neighbor_id);
|
||||||
std::vector<NodeId> x_path = path_to_forest_root(graph, id);
|
|
||||||
std::vector<NodeId> y_path = path_to_forest_root(graph, neighbor_id);
|
|
||||||
|
|
||||||
if (x_path.back() != y_path.back())
|
if (x_path.back() != y_path.back())
|
||||||
|
{
|
||||||
|
// Paths are disjoint -> augment
|
||||||
|
graph.node(x_path.front()).matched_neighbor = y_path.front();
|
||||||
|
graph.node(y_path.front()).matched_neighbor = x_path.front();
|
||||||
|
|
||||||
|
// TODO: put this into own method?
|
||||||
|
for(size_t i = 1; i < x_path.size(); i += 2)
|
||||||
{
|
{
|
||||||
// Paths are disjoint -> augment
|
graph.node(x_path[i]).matched_neighbor = x_path[i+1];
|
||||||
graph.node(x_path.front()).matched_neighbor = y_path.front();
|
graph.node(x_path[i+1]).matched_neighbor = x_path[i];
|
||||||
graph.node(y_path.front()).matched_neighbor = x_path.front();
|
|
||||||
|
|
||||||
// TODO: put this into own method?
|
|
||||||
for(size_t i = 1; i < x_path.size(); i += 2)
|
|
||||||
{
|
|
||||||
graph.node(x_path[i]).matched_neighbor = x_path[i+1];
|
|
||||||
graph.node(x_path[i+1]).matched_neighbor = x_path[i];
|
|
||||||
}
|
|
||||||
for(size_t i = 1; i < y_path.size(); i += 2)
|
|
||||||
{
|
|
||||||
graph.node(y_path[i]).matched_neighbor = y_path[i+1];
|
|
||||||
graph.node(y_path[i+1]).matched_neighbor = y_path[i];
|
|
||||||
}
|
|
||||||
// Note that since this is tail-recursion, this will not generate
|
|
||||||
// new stack frames in OPT mode
|
|
||||||
return maximum_matching(graph);
|
|
||||||
}
|
}
|
||||||
else
|
for(size_t i = 1; i < y_path.size(); i += 2)
|
||||||
{
|
{
|
||||||
// Paths are not disjoint -> shrink blossom
|
graph.node(y_path[i]).matched_neighbor = y_path[i+1];
|
||||||
size_t distance_from_x = x_path.size() - 1;
|
graph.node(y_path[i+1]).matched_neighbor = y_path[i];
|
||||||
size_t distance_from_y = y_path.size() - 1;
|
}
|
||||||
while (distance_from_x > 0 and distance_from_y > 0 and \
|
// Note that since this is tail-recursion, this will not generate
|
||||||
x_path[distance_from_x - 1] == y_path[distance_from_y - 1])
|
// new stack frames in OPT mode
|
||||||
|
return maximum_matching(graph);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Paths are not disjoint -> shrink blossom
|
||||||
|
size_t distance_from_x = x_path.size() - 1;
|
||||||
|
size_t distance_from_y = y_path.size() - 1;
|
||||||
|
while (distance_from_x > 0 and distance_from_y > 0 and \
|
||||||
|
x_path[distance_from_x - 1] == y_path[distance_from_y - 1])
|
||||||
|
{
|
||||||
|
--distance_from_x;
|
||||||
|
--distance_from_y;
|
||||||
|
}
|
||||||
|
// found first vertex of x_path \cap y_path
|
||||||
|
while (graph.root_of_ear_component(x_path[distance_from_x]) != x_path[distance_from_x])
|
||||||
|
{
|
||||||
|
++distance_from_x;
|
||||||
|
++distance_from_y;
|
||||||
|
};
|
||||||
|
// found first vertex fixed by root_of_ear_component
|
||||||
|
NodeId blossom_root_id = x_path[distance_from_x];
|
||||||
|
for(size_t i = 1; i <= distance_from_x; i += 2)
|
||||||
|
{
|
||||||
|
if (graph.root_of_ear_component(graph.ear_or_root_neighbor(x_path[i])) != blossom_root_id)
|
||||||
{
|
{
|
||||||
--distance_from_x;
|
graph.node(graph.ear_or_root_neighbor(x_path[i])).ear_or_root_neighbor = x_path[i];
|
||||||
--distance_from_y;
|
|
||||||
}
|
}
|
||||||
// found first vertex of x_path \cap y_path
|
}
|
||||||
while (graph.root_of_ear_component(x_path[distance_from_x]) != x_path[distance_from_x])
|
for(size_t i = 1; i <= distance_from_y; i += 2)
|
||||||
|
{
|
||||||
|
if (graph.root_of_ear_component(graph.ear_or_root_neighbor(y_path[i])) != blossom_root_id)
|
||||||
{
|
{
|
||||||
++distance_from_x;
|
graph.node(graph.ear_or_root_neighbor(y_path[i])).ear_or_root_neighbor = y_path[i];
|
||||||
++distance_from_y;
|
|
||||||
};
|
|
||||||
// found first vertex fixed by root_of_ear_component
|
|
||||||
NodeId blossom_root_id = x_path[distance_from_x];
|
|
||||||
for(size_t i = 1; i <= distance_from_x; i += 2)
|
|
||||||
{
|
|
||||||
if (graph.root_of_ear_component(graph.ear_or_root_neighbor(x_path[i])) != blossom_root_id)
|
|
||||||
{
|
|
||||||
graph.node(graph.ear_or_root_neighbor(x_path[i])).ear_or_root_neighbor = x_path[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(size_t i = 1; i <= distance_from_y; i += 2)
|
|
||||||
{
|
|
||||||
if (graph.root_of_ear_component(graph.ear_or_root_neighbor(y_path[i])) != blossom_root_id)
|
|
||||||
{
|
|
||||||
graph.node(graph.ear_or_root_neighbor(y_path[i])).ear_or_root_neighbor = y_path[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (graph.root_of_ear_component(x_path.front()) != blossom_root_id)
|
|
||||||
{
|
|
||||||
graph.node(x_path.front()).ear_or_root_neighbor = y_path.front();
|
|
||||||
}
|
|
||||||
if (graph.root_of_ear_component(y_path.front()) != blossom_root_id)
|
|
||||||
{
|
|
||||||
graph.node(x_path.front()).ear_or_root_neighbor = x_path.front();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (graph.root_of_ear_component(x_path.front()) != blossom_root_id)
|
||||||
|
{
|
||||||
|
graph.node(x_path.front()).ear_or_root_neighbor = y_path.front();
|
||||||
|
}
|
||||||
|
if (graph.root_of_ear_component(y_path.front()) != blossom_root_id)
|
||||||
|
{
|
||||||
|
graph.node(x_path.front()).ear_or_root_neighbor = x_path.front();
|
||||||
|
}
|
||||||
|
|
||||||
// Update root indices
|
// Update root indices
|
||||||
for(size_t i = 0; i <= distance_from_x; ++i)
|
for(size_t i = 0; i <= distance_from_x; ++i)
|
||||||
{
|
{
|
||||||
graph.node(x_path[i]).root_of_ear_component = blossom_root_id;
|
graph.node(x_path[i]).root_of_ear_component = blossom_root_id;
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i <= distance_from_y; ++i)
|
for(size_t i = 0; i <= distance_from_y; ++i)
|
||||||
{
|
{
|
||||||
graph.node(y_path[i]).root_of_ear_component = blossom_root_id;
|
graph.node(y_path[i]).root_of_ear_component = blossom_root_id;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
graph.node(id).scanned = true;
|
||||||
}
|
}
|
||||||
return graph;
|
return graph;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue