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