| 1 | <HTML> |
|---|
| 2 | <!-- |
|---|
| 3 | -- Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000 |
|---|
| 4 | -- |
|---|
| 5 | -- Distributed under the Boost Software License, Version 1.0. |
|---|
| 6 | -- (See accompanying file LICENSE_1_0.txt or copy at |
|---|
| 7 | -- http://www.boost.org/LICENSE_1_0.txt) |
|---|
| 8 | --> |
|---|
| 9 | <Head> |
|---|
| 10 | <Title>Boost Graph Library: Incremental Connected Components</Title> |
|---|
| 11 | <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" |
|---|
| 12 | ALINK="#ff0000"> |
|---|
| 13 | <IMG SRC="../../../boost.png" |
|---|
| 14 | ALT="C++ Boost" width="277" height="86"> |
|---|
| 15 | |
|---|
| 16 | <BR Clear> |
|---|
| 17 | |
|---|
| 18 | <H1>Incremental Connected Components</H1> |
|---|
| 19 | |
|---|
| 20 | <P> |
|---|
| 21 | This section describes a family of functions and classes that work |
|---|
| 22 | together to calculate the connected components of an undirected graph. |
|---|
| 23 | The algorithm used here is based on the disjoint-sets (fast |
|---|
| 24 | union-find) data structure [<A |
|---|
| 25 | HREF="bibliography.html#clr90">8</A>,<A |
|---|
| 26 | HREF="bibliography.html#tarjan83:_data_struct_network_algo">27</A>] |
|---|
| 27 | which is a good method to use for situations where the graph is |
|---|
| 28 | growing (edges are being added) and the connected components |
|---|
| 29 | information needs to be updated repeatedly. This method does not cover |
|---|
| 30 | the situation where edges are both added and removed from the graph, |
|---|
| 31 | hence it is called <b><i>incremental</i></b><a |
|---|
| 32 | href="bibliography.html#eppstein97:dynamic_graph">[42]</a> (and not |
|---|
| 33 | fully dynamic). The disjoint-sets class is described in Section <A |
|---|
| 34 | HREF="../../disjoint_sets/disjoint_sets.html">Disjoint Sets</A>. |
|---|
| 35 | |
|---|
| 36 | <P> |
|---|
| 37 | The following five operations are the primary functions that you will |
|---|
| 38 | use to calculate and maintain the connected components. The objects |
|---|
| 39 | used here are a graph <TT>g</TT>, a disjoint-sets structure <TT>ds</TT>, |
|---|
| 40 | and vertices <TT>u</TT> and <TT>v</TT>. |
|---|
| 41 | |
|---|
| 42 | <P> |
|---|
| 43 | |
|---|
| 44 | <UL> |
|---|
| 45 | <LI><TT>initialize_incremental_components(g, ds)</TT> |
|---|
| 46 | <BR> |
|---|
| 47 | Basic initialization of the disjoint-sets structure. Each |
|---|
| 48 | vertex in the graph <TT>g</TT> is in its own set. |
|---|
| 49 | </LI> |
|---|
| 50 | <LI><TT>incremental_components(g, ds)</TT> |
|---|
| 51 | <BR> |
|---|
| 52 | The connected components are calculated based on the edges in the graph |
|---|
| 53 | <TT>g</TT> and the information is embedded in <TT>ds</TT>. |
|---|
| 54 | </LI> |
|---|
| 55 | <LI><TT>ds.find_set(v)</TT> |
|---|
| 56 | <BR> |
|---|
| 57 | Extracts the component information for vertex <TT>v</TT> from the |
|---|
| 58 | disjoint-sets. |
|---|
| 59 | </LI> |
|---|
| 60 | <LI><TT>ds.union_set(u, v)</TT> |
|---|
| 61 | <BR> |
|---|
| 62 | Update the disjoint-sets structure when edge <i>(u,v)</i> is added to the graph. |
|---|
| 63 | </LI> |
|---|
| 64 | </UL> |
|---|
| 65 | |
|---|
| 66 | <P> |
|---|
| 67 | |
|---|
| 68 | <H3>Complexity</H3> |
|---|
| 69 | |
|---|
| 70 | <P> |
|---|
| 71 | The time complexity for the whole process is <i>O(V + E |
|---|
| 72 | alpha(E,V))</i> where <i>E</i> is the total number of edges in the |
|---|
| 73 | graph (by the end of the process) and <i>V</i> is the number of |
|---|
| 74 | vertices. <i>alpha</i> is the inverse of Ackermann's function which |
|---|
| 75 | has explosive recursively exponential growth. Therefore its inverse |
|---|
| 76 | function grows <I>very</I> slowly. For all practical purposes |
|---|
| 77 | <i>alpha(m,n) <= 4</i> which means the time complexity is only |
|---|
| 78 | slightly larger than <i>O(V + E)</i>. |
|---|
| 79 | |
|---|
| 80 | <P> |
|---|
| 81 | |
|---|
| 82 | <H3>Example</H3> |
|---|
| 83 | |
|---|
| 84 | <P> |
|---|
| 85 | Maintain the connected components of a graph while adding edges using |
|---|
| 86 | the disjoint-sets data structure. The full source code for this |
|---|
| 87 | example can be found in <a |
|---|
| 88 | href="../example/incremental_components.cpp"><TT>examples/incremental_components.cpp</TT></a>. |
|---|
| 89 | |
|---|
| 90 | <P> |
|---|
| 91 | <PRE> |
|---|
| 92 | typedef adjacency_list <vecS, vecS, undirectedS> Graph; |
|---|
| 93 | typedef graph_traits<Graph>::vertex_descriptor Vertex; |
|---|
| 94 | typedef graph_traits<Graph>::vertices_size_type size_type; |
|---|
| 95 | |
|---|
| 96 | const int N = 6; |
|---|
| 97 | Graph G(N); |
|---|
| 98 | |
|---|
| 99 | std::vector<size_type> rank(num_vertices(G)); |
|---|
| 100 | std::vector<Vertex> parent(num_vertices(G)); |
|---|
| 101 | typedef size_type* Rank; |
|---|
| 102 | typedef Vertex* Parent; |
|---|
| 103 | disjoint_sets<Rank, Parent> ds(&rank[0], &parent[0]); |
|---|
| 104 | |
|---|
| 105 | initialize_incremental_components(G, ds); |
|---|
| 106 | incremental_components(G, ds); |
|---|
| 107 | |
|---|
| 108 | graph_traits<Graph>::edge_descriptor e; |
|---|
| 109 | bool flag; |
|---|
| 110 | boost::tie(e,flag) = add_edge(0, 1, G); |
|---|
| 111 | ds.union_set(0,1); |
|---|
| 112 | |
|---|
| 113 | boost::tie(e,flag) = add_edge(1, 4, G); |
|---|
| 114 | ds.union_set(1,4); |
|---|
| 115 | |
|---|
| 116 | boost::tie(e,flag) = add_edge(4, 0, G); |
|---|
| 117 | ds.union_set(4,0); |
|---|
| 118 | |
|---|
| 119 | boost::tie(e,flag) = add_edge(2, 5, G); |
|---|
| 120 | ds.union_set(2,5); |
|---|
| 121 | |
|---|
| 122 | cout << "An undirected graph:" << endl; |
|---|
| 123 | print_graph(G, get(vertex_index, G)); |
|---|
| 124 | cout << endl; |
|---|
| 125 | |
|---|
| 126 | graph_traits<Graph>::vertex_iterator i,end; |
|---|
| 127 | for (boost::tie(i, end) = vertices(G); i != end; ++i) |
|---|
| 128 | cout << "representative[" << *i << "] = " << |
|---|
| 129 | ds.find_set(*i) << endl;; |
|---|
| 130 | cout << endl; |
|---|
| 131 | |
|---|
| 132 | typedef component_index<unsigned int> Components; |
|---|
| 133 | Components components(&parent[0], &parent[0] + parent.size()); |
|---|
| 134 | |
|---|
| 135 | for (Components::size_type c = 0; c < components.size(); ++c) { |
|---|
| 136 | cout << "component " << c << " contains: "; |
|---|
| 137 | Components::value_type::iterator |
|---|
| 138 | j = components[c].begin(), |
|---|
| 139 | jend = components[c].end(); |
|---|
| 140 | for ( ; j != jend; ++j) |
|---|
| 141 | cout << *j << " "; |
|---|
| 142 | cout << endl; |
|---|
| 143 | } |
|---|
| 144 | </PRE> |
|---|
| 145 | |
|---|
| 146 | <P> |
|---|
| 147 | <hr> |
|---|
| 148 | <p> |
|---|
| 149 | |
|---|
| 150 | <H2><A NAME="sec:initialize-incremental-components"></A> |
|---|
| 151 | <TT>initialize_incremental_components</TT> |
|---|
| 152 | </H2> |
|---|
| 153 | |
|---|
| 154 | <P> |
|---|
| 155 | <DIV ALIGN="left"> |
|---|
| 156 | <TABLE CELLPADDING=3 border> |
|---|
| 157 | <TR><TH ALIGN="LEFT"><B>Graphs:</B></TH> |
|---|
| 158 | <TD ALIGN="LEFT">undirected</TD> |
|---|
| 159 | </TR> |
|---|
| 160 | <TR><TH ALIGN="LEFT"><B>Properties:</B></TH> |
|---|
| 161 | <TD ALIGN="LEFT">rank, parent (in disjoint-sets)</TD> |
|---|
| 162 | </TR> |
|---|
| 163 | <TR><TH ALIGN="LEFT"><B>Complexity:</B></TH> |
|---|
| 164 | <TD></TD> |
|---|
| 165 | </TR> |
|---|
| 166 | </TABLE> |
|---|
| 167 | </DIV> |
|---|
| 168 | |
|---|
| 169 | <P> |
|---|
| 170 | <PRE> |
|---|
| 171 | template <class VertexListGraph, class DisjointSets> |
|---|
| 172 | void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds) |
|---|
| 173 | </PRE> |
|---|
| 174 | |
|---|
| 175 | <P> |
|---|
| 176 | This prepares the disjoint-sets data structure for the incremental |
|---|
| 177 | connected components algorithm by making each vertex in the graph a |
|---|
| 178 | member of its own component (or set). |
|---|
| 179 | |
|---|
| 180 | <P> |
|---|
| 181 | |
|---|
| 182 | <H3>Where Defined</H3> |
|---|
| 183 | |
|---|
| 184 | <P> |
|---|
| 185 | <a href="../../../boost/graph/incremental_components.hpp"><TT>boost/graph/incremental_components.hpp</TT></a> |
|---|
| 186 | |
|---|
| 187 | <p> |
|---|
| 188 | <hr> |
|---|
| 189 | <P> |
|---|
| 190 | |
|---|
| 191 | <H2><A NAME="sec:incremental-components"></A> |
|---|
| 192 | <TT>incremental_components</TT> |
|---|
| 193 | </H2> |
|---|
| 194 | |
|---|
| 195 | <P> |
|---|
| 196 | <DIV ALIGN="left"> |
|---|
| 197 | <TABLE CELLPADDING=3 border> |
|---|
| 198 | <TR><TH ALIGN="LEFT"><B>Graphs:</B></TH> |
|---|
| 199 | <TD ALIGN="LEFT">undirected</TD> |
|---|
| 200 | </TR> |
|---|
| 201 | <TR><TH ALIGN="LEFT"><B>Properties:</B></TH> |
|---|
| 202 | <TD ALIGN="LEFT">rank, parent (in disjoint-sets)</TD> |
|---|
| 203 | </TR> |
|---|
| 204 | <TR><TH ALIGN="LEFT"><B>Complexity:</B></TH> |
|---|
| 205 | <TD ALIGN="LEFT"><i>O(E)</i></TD> |
|---|
| 206 | </TR> |
|---|
| 207 | </TABLE> |
|---|
| 208 | </DIV> |
|---|
| 209 | |
|---|
| 210 | <p> |
|---|
| 211 | <PRE> |
|---|
| 212 | template <class EdgeListGraph, class DisjointSets> |
|---|
| 213 | void incremental_components(EdgeListGraph& g, DisjointSets& ds) |
|---|
| 214 | </PRE> |
|---|
| 215 | |
|---|
| 216 | <P> |
|---|
| 217 | This function calculates the connected components of the graph, |
|---|
| 218 | embedding the results in the disjoint-sets data structure. |
|---|
| 219 | |
|---|
| 220 | <P> |
|---|
| 221 | |
|---|
| 222 | <H3>Where Defined</H3> |
|---|
| 223 | |
|---|
| 224 | <P> |
|---|
| 225 | <a href="../../../boost/graph/incremental_components.hpp"><TT>boost/graph/incremental_components.hpp</TT></a> |
|---|
| 226 | |
|---|
| 227 | <P> |
|---|
| 228 | |
|---|
| 229 | <H3>Requirements on Types</H3> |
|---|
| 230 | |
|---|
| 231 | <P> |
|---|
| 232 | |
|---|
| 233 | <UL> |
|---|
| 234 | <LI>The graph type must be a model of <a href="./EdgeListGraph.html">EdgeListGraph</a>. |
|---|
| 235 | </LI> |
|---|
| 236 | </UL> |
|---|
| 237 | |
|---|
| 238 | <P> |
|---|
| 239 | <hr> |
|---|
| 240 | <p> |
|---|
| 241 | |
|---|
| 242 | <H2><A NAME="sec:same-component"> |
|---|
| 243 | <TT>same_component</TT></A> |
|---|
| 244 | </H2> |
|---|
| 245 | |
|---|
| 246 | <P> |
|---|
| 247 | <DIV ALIGN="left"> |
|---|
| 248 | <TABLE CELLPADDING=3 border> |
|---|
| 249 | <TR><TH ALIGN="LEFT"><B>Properties:</B></TH> |
|---|
| 250 | <TD ALIGN="LEFT">rank, parent (in disjoint-sets)</TD> |
|---|
| 251 | </TR> |
|---|
| 252 | <TR><TH ALIGN="LEFT"><B>Complexity:</B></TH> |
|---|
| 253 | <TD ALIGN="LEFT"><i>O(alpha(E,V))</i></TD> |
|---|
| 254 | </TR> |
|---|
| 255 | </TABLE> |
|---|
| 256 | </DIV> |
|---|
| 257 | |
|---|
| 258 | <P> |
|---|
| 259 | <PRE> |
|---|
| 260 | template <class Vertex, class DisjointSet> |
|---|
| 261 | bool same_component(Vertex u, Vertex v, DisjointSet& ds) |
|---|
| 262 | </PRE> |
|---|
| 263 | |
|---|
| 264 | <P> |
|---|
| 265 | This function determines whether <TT>u</TT> and <TT>v</TT> are in the same |
|---|
| 266 | component. |
|---|
| 267 | |
|---|
| 268 | <P> |
|---|
| 269 | |
|---|
| 270 | <H3>Where Defined</H3> |
|---|
| 271 | |
|---|
| 272 | <P> |
|---|
| 273 | <a href="../../../boost/graph/incremental_components.hpp"><TT>boost/graph/incremental_components.hpp</TT></a> |
|---|
| 274 | |
|---|
| 275 | <P> |
|---|
| 276 | |
|---|
| 277 | <H3>Requirements on Types</H3> |
|---|
| 278 | |
|---|
| 279 | <P> |
|---|
| 280 | |
|---|
| 281 | <UL> |
|---|
| 282 | <LI><TT>Vertex</TT> must be compatible with the rank and parent |
|---|
| 283 | property maps of the <TT>DisjointSets</TT> data structure. |
|---|
| 284 | </LI> |
|---|
| 285 | </UL> |
|---|
| 286 | |
|---|
| 287 | <P> |
|---|
| 288 | <hr> |
|---|
| 289 | <p> |
|---|
| 290 | |
|---|
| 291 | <H2><A NAME="sec:component-index"></A> |
|---|
| 292 | <TT>component_index</TT> |
|---|
| 293 | </H2> |
|---|
| 294 | |
|---|
| 295 | <p> |
|---|
| 296 | <PRE> |
|---|
| 297 | component_index<Index> |
|---|
| 298 | </PRE> |
|---|
| 299 | |
|---|
| 300 | <P> |
|---|
| 301 | The is a class that provides an STL container-like view for the |
|---|
| 302 | components of the graph. Each component is a container-like object, |
|---|
| 303 | and the <TT>component_index</TT> object provides access to the |
|---|
| 304 | component objects via <TT>operator[]</TT>. A <TT>component_index</TT> |
|---|
| 305 | object is initialized with the parents property in the disjoint-sets |
|---|
| 306 | calculated from the <TT>incremental_components()</TT> function. |
|---|
| 307 | |
|---|
| 308 | <P> |
|---|
| 309 | |
|---|
| 310 | <H3>Where Defined</H3> |
|---|
| 311 | |
|---|
| 312 | <P> |
|---|
| 313 | <a href="../../../boost/graph/incremental_components.hpp"><TT>boost/graph/incremental_components.hpp</TT></a> |
|---|
| 314 | |
|---|
| 315 | <P> |
|---|
| 316 | |
|---|
| 317 | <H3>Members</H3> |
|---|
| 318 | |
|---|
| 319 | <P> |
|---|
| 320 | |
|---|
| 321 | <table border> |
|---|
| 322 | |
|---|
| 323 | <tr> |
|---|
| 324 | <th>Member</th> <th>Description</th> |
|---|
| 325 | </tr> |
|---|
| 326 | |
|---|
| 327 | <tr> |
|---|
| 328 | <td><tt>size_type</tt></td> |
|---|
| 329 | <td>The type used for representing the number of components.</td> |
|---|
| 330 | </tr> |
|---|
| 331 | |
|---|
| 332 | |
|---|
| 333 | <tr> |
|---|
| 334 | <td><tt>value_type</tt></td> |
|---|
| 335 | <td> |
|---|
| 336 | The type for a component object. The component type has the following members. |
|---|
| 337 | </td> |
|---|
| 338 | </tr> |
|---|
| 339 | |
|---|
| 340 | <tr> |
|---|
| 341 | <td><tt>value_type::value_type</tt></td> |
|---|
| 342 | <td> |
|---|
| 343 | The value type of a component object is a vertex ID. |
|---|
| 344 | </td> |
|---|
| 345 | </tr> |
|---|
| 346 | |
|---|
| 347 | <tr> |
|---|
| 348 | <td><tt>value_type::iterator</tt></td> |
|---|
| 349 | <td> |
|---|
| 350 | This iterator can be used to traverse all of the vertices |
|---|
| 351 | in the component. This iterator dereferences to give a vertex ID. |
|---|
| 352 | </td> |
|---|
| 353 | </tr> |
|---|
| 354 | |
|---|
| 355 | <tr> |
|---|
| 356 | <td><tt>value_type::const_iterator</tt></td> |
|---|
| 357 | <td> |
|---|
| 358 | The const iterator. |
|---|
| 359 | </td> |
|---|
| 360 | </tr> |
|---|
| 361 | |
|---|
| 362 | <tr> |
|---|
| 363 | <td><tt>value_type::iterator value_type::begin() const</tt></td> |
|---|
| 364 | <td> |
|---|
| 365 | Return an iterator pointing to the first vertex in the component. |
|---|
| 366 | </td> |
|---|
| 367 | </tr> |
|---|
| 368 | |
|---|
| 369 | <tr> |
|---|
| 370 | <td><tt>value_type::iterator value_type::end() const</tt></td> |
|---|
| 371 | <td> |
|---|
| 372 | Return an iterator pointing past the end of the last vertex in the |
|---|
| 373 | component. |
|---|
| 374 | </td> |
|---|
| 375 | <tr> |
|---|
| 376 | |
|---|
| 377 | <tr> |
|---|
| 378 | <td> |
|---|
| 379 | <tt> |
|---|
| 380 | template <class ComponentsContainer> |
|---|
| 381 | component_index(const ComponentsContainer& c) |
|---|
| 382 | </tt> |
|---|
| 383 | </td> |
|---|
| 384 | <td> |
|---|
| 385 | Construct the <TT>component_index</TT> using the information |
|---|
| 386 | from the components container <TT>c</TT> which was the result |
|---|
| 387 | of executing <TT>connected_components_on_edgelist</TT>. |
|---|
| 388 | </td> |
|---|
| 389 | </tr> |
|---|
| 390 | |
|---|
| 391 | <tr> |
|---|
| 392 | <td><tt>value_type operator[](size_type i)</tt></td> |
|---|
| 393 | <td> |
|---|
| 394 | Returns the <TT>i</TT>th component in the graph. |
|---|
| 395 | </td> |
|---|
| 396 | </tr> |
|---|
| 397 | |
|---|
| 398 | <tr> |
|---|
| 399 | <td><tt>size_type component_index::size()</tt></td> |
|---|
| 400 | <td> |
|---|
| 401 | Returns the number of components in the graph. |
|---|
| 402 | </td> |
|---|
| 403 | |
|---|
| 404 | </table> |
|---|
| 405 | |
|---|
| 406 | <br> |
|---|
| 407 | <HR> |
|---|
| 408 | <TABLE> |
|---|
| 409 | <TR valign=top> |
|---|
| 410 | <TD nowrap>Copyright © 2000-2001</TD><TD> |
|---|
| 411 | <A HREF="../../../people/jeremy_siek.htm">Jeremy Siek</A>, |
|---|
| 412 | Indiana University (<A |
|---|
| 413 | HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)<br> |
|---|
| 414 | <A HREF="../../../people/liequan_lee.htm">Lie-Quan Lee</A>, Indiana University (<A HREF="mailto:llee@cs.indiana.edu">llee@cs.indiana.edu</A>)<br> |
|---|
| 415 | <A HREF=http://www.osl.iu.edu/~lums>Andrew Lumsdaine</A>, |
|---|
| 416 | Indiana University (<A |
|---|
| 417 | HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>) |
|---|
| 418 | </TD></TR></TABLE> |
|---|
| 419 | |
|---|
| 420 | </BODY> |
|---|
| 421 | </HTML> |
|---|