1- /* *
1+ /* *
22 * @file connected_components.hpp
33 *
44 * @brief Single-Source Shortest paths and shortest sistances algorithms using Dijkstra &
2121#include " graph/views/breadth_first_search.hpp"
2222#include < stack>
2323#include < random>
24- #include < numeric>
2524
2625#ifndef GRAPH_CC_HPP
2726# define GRAPH_CC_HPP
@@ -94,25 +93,32 @@ size_t connected_components(G&& g, // graph
9493 Component& component // out: connected component assignment
9594) {
9695 size_t N (size (vertices (g)));
97- std::vector<bool > visited (N, false );
9896 using CT = typename std::decay<decltype (*component.begin ())>::type;
9997 std::fill (component.begin (), component.end (), std::numeric_limits<CT>::max ());
10098
99+ std::stack<vertex_id_t <G>> S;
101100 CT cid = 0 ;
102- for (auto && [ uid, u] : views::vertexlist (g) ) {
103- if (visited [uid]) {
101+ for (vertex_id_t <G> uid = 0 ; uid < N; ++uid ) {
102+ if (component [uid] < std::numeric_limits<CT>:: max () ) {
104103 continue ;
105104 }
106- visited[uid] = true ;
107- component[uid] = cid;
108- if (!size (edges (g, u))) {
109- ++cid;
105+
106+ if (!size (edges (g, uid))) {
107+ component[uid] = cid++;
110108 continue ;
111109 }
112- vertices_breadth_first_search_view<G, void > bfs (g, uid);
113- for (auto && [vid, v] : bfs) {
114- component[vid] = cid;
115- visited[vid] = true ;
110+
111+ component[uid] = cid;
112+ S.push (uid);
113+ while (!S.empty ()) {
114+ auto vid = S.top ();
115+ S.pop ();
116+ for (auto && [wid, vw] : views::incidence (g, vid)) {
117+ if (component[wid] == std::numeric_limits<CT>::max ()) {
118+ component[wid] = cid;
119+ S.push (wid);
120+ }
121+ }
116122 }
117123 ++cid;
118124 }
@@ -156,7 +162,7 @@ template <typename vertex_id_t, random_access_range Component>
156162static vertex_id_t sample_frequent_element (Component& component, size_t num_samples = 1024 ) {
157163 std::unordered_map<vertex_id_t , int > counts (32 );
158164 std::mt19937 gen;
159- std::uniform_int_distribution<vertex_id_t > distribution (0 , static_cast < vertex_id_t >( component.size () - 1 ) );
165+ std::uniform_int_distribution<vertex_id_t > distribution (0 , component.size () - 1 );
160166
161167 for (size_t i = 0 ; i < num_samples; ++i) {
162168 vertex_id_t sample = distribution (gen);
@@ -172,9 +178,9 @@ template <adjacency_list G, random_access_range Component>
172178requires random_access_range<vertex_range_t <G>> && integral<vertex_id_t <G>> &&
173179 std::convertible_to<range_value_t <Component>, vertex_id_t <G>> &&
174180 std::convertible_to<vertex_id_t <G>, range_value_t <Component>>
175- size_t afforest (G&& g, // graph
176- Component& component, // out: connected component assignment
177- const size_t neighbor_rounds = 2 ) {
181+ void afforest (G&& g, // graph
182+ Component& component, // out: connected component assignment
183+ const size_t neighbor_rounds = 2 ) {
178184 size_t N (size (vertices (g)));
179185 std::iota (component.begin (), component.end (), 0 );
180186
@@ -205,34 +211,16 @@ size_t afforest(G&& g, // graph
205211 }
206212
207213 compress (component);
208- vertex_id_t <G> target_id = 0 ;
209- std::map<vertex_id_t <G>, vertex_id_t <G>> reindex;
210- for (vertex_id_t <G> vtx = 0 ; vtx < N; ++vtx) {
211- if (!reindex.empty ()) {
212- auto it = reindex.find (component[vtx]);
213- if (it != reindex.end ()) {
214- component[vtx] = (*it).second ;
215- }
216- } else if (component[vtx] == target_id) {
217- ++target_id;
218- } else if (component[vtx] > target_id) {
219- reindex.insert (pair (component[vtx], target_id));
220- component[vtx] = target_id;
221- ++target_id;
222- }
223- }
224-
225- return target_id;
226214}
227215
228216template <adjacency_list G, adjacency_list GT, random_access_range Component>
229217requires random_access_range<vertex_range_t <G>> && integral<vertex_id_t <G>> &&
230218 std::convertible_to<range_value_t <Component>, vertex_id_t <G>> &&
231219 std::convertible_to<vertex_id_t <G>, range_value_t <Component>>
232- size_t afforest (G&& g, // graph
233- GT&& g_t , // graph transpose
234- Component& component, // out: connected component assignment
235- const size_t neighbor_rounds = 2 ) {
220+ void afforest (G&& g, // graph
221+ GT&& g_t , // graph transpose
222+ Component& component, // out: connected component assignment
223+ const size_t neighbor_rounds = 2 ) {
236224 size_t N (size (vertices (g)));
237225 std::iota (component.begin (), component.end (), 0 );
238226
@@ -266,24 +254,6 @@ size_t afforest(G&& g, // graph
266254 }
267255
268256 compress (component);
269- vertex_id_t <G> target_id = 0 ;
270- std::map<vertex_id_t <G>, vertex_id_t <G>> reindex;
271- for (vertex_id_t <G> vtx = 0 ; vtx < N; ++vtx) {
272- if (!reindex.empty ()) {
273- auto it = reindex.find (component[vtx]);
274- if (it != reindex.end ()) {
275- component[vtx] = (*it).second ;
276- }
277- } else if (component[vtx] == target_id) {
278- ++target_id;
279- } else if (component[vtx] > target_id) {
280- reindex.insert (pair (component[vtx], target_id));
281- component[vtx] = target_id;
282- ++target_id;
283- }
284- }
285-
286- return target_id;
287257}
288258
289259} // namespace graph
0 commit comments