diff --git a/include/boost/graph/connected_components.hpp b/include/boost/graph/connected_components.hpp index 0e98512d0..89b301075 100644 --- a/include/boost/graph/connected_components.hpp +++ b/include/boost/graph/connected_components.hpp @@ -69,8 +69,12 @@ connected_components(const Graph& g, ComponentMap c, const bgl_named_params< P, T, R >& params BOOST_GRAPH_ENABLE_IF_MODELS_PARM( Graph, vertex_list_graph_tag)) { - if (num_vertices(g) == 0) + // num_vertices also counts the vertices hidden by a filtered_graph + const auto vertex_range = vertices(g); + if (vertex_range.first == vertex_range.second) + { return 0; + } typedef typename graph_traits< Graph >::vertex_descriptor Vertex; BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< ComponentMap, Vertex >)); @@ -91,8 +95,12 @@ connected_components(const Graph& g, ComponentMap c BOOST_GRAPH_ENABLE_IF_MODELS_PARM( Graph, vertex_list_graph_tag)) { - if (num_vertices(g) == 0) + // num_vertices also counts the vertices hidden by a filtered_graph + const auto vertex_range = vertices(g); + if (vertex_range.first == vertex_range.second) + { return 0; + } typedef typename graph_traits< Graph >::vertex_descriptor Vertex; BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< ComponentMap, Vertex >)); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index acb9b6bbf..156872d4f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -128,6 +128,7 @@ alias graph_test_regular : [ run floyd_warshall_test.cpp ] [ run astar_search_test.cpp ] [ run biconnected_components_test.cpp ] + [ run connected_components_test.cpp ] [ run min_degree_empty.cpp ] [ run cuthill_mckee_ordering.cpp ] [ run king_ordering.cpp ] diff --git a/test/connected_components_test.cpp b/test/connected_components_test.cpp new file mode 100644 index 000000000..e41dbdb2f --- /dev/null +++ b/test/connected_components_test.cpp @@ -0,0 +1,44 @@ +//======================================================================= +// Copyright (c) 2026 Arnaud Becheler +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +#include +#include +#include +#include + +using Graph = ::boost::adjacency_list< ::boost::vecS, ::boost::vecS, ::boost::undirectedS >; +using Vertex = ::boost::graph_traits< Graph >::vertex_descriptor; + +// Hides every vertex. +struct keep_none +{ + bool operator()(Vertex) const { return false; } +}; + +using FilteredGraph = ::boost::filtered_graph< Graph, ::boost::keep_all, keep_none >; + +// Checks that a filtered graph with no visible vertex has no components. +void test_all_vertices_filtered_out() +{ + const Graph base(3); + const FilteredGraph g(base, ::boost::keep_all(), keep_none()); + + std::vector< int > component_vec(::boost::num_vertices(g), -1); + auto component_map = ::boost::make_iterator_property_map(component_vec.begin(), ::boost::get(::boost::vertex_index, g)); + const int num_components = ::boost::connected_components(g, component_map); + + BOOST_TEST_EQ(num_components, 0); +} + +int main() +{ + test_all_vertices_filtered_out(); + return ::boost::report_errors(); +}