-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconnected_components.cpp
98 lines (85 loc) · 2.55 KB
/
connected_components.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "connected_components.hpp"
#include "logging.hpp"
void dfs(const ugraph_t & graph,
const std::vector< bool > & smpl,
std::vector< int > & components_map,
std::vector< ugraph_vertex_t > & stack,
ugraph_vertex_t root,
int component_id) {
using namespace boost;
stack.clear();
stack.push_back(root);
components_map[root] = component_id;
while(!stack.empty()) {
ugraph_vertex_t u = stack.back();
stack.pop_back();
BGL_FORALL_OUTEDGES(u, e, graph, ugraph_t) {
if (smpl[ graph[e].index ]) {
ugraph_vertex_t v = target(e, graph);
if (components_map[v] < 0) {
components_map[v] = component_id;
stack.push_back(v);
}
}
}
}
}
void connected_components(const ugraph_t & graph,
const std::vector< bool > & smpl,
std::vector< int > & components_map,
std::vector< ugraph_vertex_t > & stack) {
using namespace boost;
// initialize
stack.clear();
for (size_t i=0; i < components_map.size(); i++) {
components_map[i] = -1;
}
int component_id = 0;
BGL_FORALL_VERTICES(root, graph, ugraph_t) {
if (components_map[root] < 0) {
dfs(graph, smpl, components_map, stack, root, component_id++);
}
}
}
void union_find(const ugraph_t & graph,
Xorshift1024star & rnd,
std::vector< size_t > & ranks,
std::vector< int > & roots) {
using namespace boost;
std::fill(ranks.begin(), ranks.end(), 0);
// Each node starts in it own connected component
for (ugraph_vertex_t u=0; u < ranks.size(); ++u) {
roots[u] = u;
}
BGL_FORALL_EDGES(e, graph, ugraph_t) {
// sample the edge!
if (rnd.next_double() <= graph[e].probability) {
ugraph_vertex_t u = source(e, graph);
ugraph_vertex_t v = target(e, graph);
// find roots
// TODO apply path compression
while (u != roots[u]) { u = roots[u]; }
while (v != roots[v]) { v = roots[v]; }
if (u != v) {
// the nodes are in different connected components
size_t
rank_u = ranks[u],
rank_v = ranks[v];
if (rank_u < rank_v) {
roots[u] = v;
} else if (rank_u > rank_v) {
roots[v] = u;
} else {
roots[v] = u;
ranks[u]++;
}
}
}
}
// Compress the components
for (ugraph_vertex_t u=0; u < ranks.size(); ++u) {
ugraph_vertex_t r = u;
while ( r != roots[r] ) { r = roots[r]; }
roots[u] = r;
}
}