2
0
mirror of https://github.com/boostorg/graph.git synced 2026-01-24 18:02:19 +00:00
Files
graph/doc/dynamic_components.html
2000-12-08 22:18:53 +00:00

423 lines
10 KiB
HTML

<HTML>
<!--
-- Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: Dynamic Connected Components</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1>Dynamic Connected Components</H1>
<P>
This section describes a family of functions and classes that
calculate the connected components of an undirected graph. The
algorithm used here is based on the disjoint-sets data
structure&nbsp;[<A
HREF="bibliography.html#clr90">8</A>,<A
HREF="bibliography.html#tarjan83:_data_struct_network_algo">27</A>] which is
the best method for situations where the graph is growing (edges are
being added) and the connected components information needs to be
updated repeatedly. The disjoint-sets class is described in
Section <A HREF="../../disjoint_sets/disjoint_sets.html">Disjoint Sets</A>.
<P>
The following five operations are the primary functions that you will
use to calculate and maintain the connected components. The objects
used here are a graph <TT>g</TT>, a disjoint-sets structure <TT>ds</TT>,
and vertices <TT>u</TT> and <TT>v</TT>.
<P>
<UL>
<LI><TT>initialize_dynamic_components(g, ds)</TT>
<BR>
Basic initialization of the disjoint-sets structure. Each
vertex in the graph <TT>g</TT> is in its own set.
</LI>
<LI><TT>dynamic_connected_components(g, ds)</TT>
<BR>
The connected components are calculated based on the edges in the graph
<TT>g</TT> and the information is embedded in <TT>ds</TT>.
</LI>
<LI><TT>ds.find_set(v)</TT>
<BR>
Extracts the component information for vertex <TT>v</TT> from the
disjoint-sets.
</LI>
<LI><TT>ds.union_set(u, v)</TT>
<BR>
Update the disjoint-sets structure when edge <i>(u,v)</i> is added to the graph.
</LI>
</UL>
<P>
<H3>Complexity</H3>
<P>
The time complexity for the whole process is <i>O(V + E
alpha(E,V))</i> where <i>E</i> is the total number of edges in the
graph (by the end of the process) and <i>V</i> is the number of
vertices. <i>alpha</i> is the inverse of Ackermann's function which
has explosive recursively exponential growth. Therefore its inverse
function grows <I>very</I> slowly. For all practical purposes
<i>alpha(m,n) <= 4</i> which means the time complexity is only
slightly larger than <i>O(V + E)</i>.
<P>
<H3>Example</H3>
<P>
Maintain the connected components of a graph while adding edges using
the disjoint-sets data structure. The full source code for this
example can be found in <a
href="../example/dynamic_components.cpp"><TT>examples/dynamic_components.cpp</TT></a>.
<P>
<PRE>
// Create a graph
typedef adjacency_list &lt;vecS, vecS, undirectedS&gt; Graph;
typedef Graph::vertex_descriptor Vertex;
const int N = 6;
Graph G(N);
add_edge(0, 1, G);
add_edge(1, 4, G);
// create the disjoint-sets structure, which requires
// rank and parent vertex properties
std::vector&lt;Vertex&gt; rank(num_vertices(G));
std::vector&lt;Vertex&gt; parent(num_vertices(G));
typedef std::vector&lt;Graph::size_type&gt;::iterator Rank;
typedef std::vector&lt;Vertex&gt;::iterator Parent;
disjoint_sets&lt;Rank, Parent&gt; ds(rank.begin(), parent.begin());
// determine the connected components
// the results are embedded in the disjoint-sets structure
initialize_dynamic_components(G, ds);
dynamic_connected_components(G, ds);
Graph::edge_descriptor e;
bool flag;
// Add a couple more edges and update the disjoint-sets
tie(e,flag) = add_edge(4, 0, G);
ds.union_set(4,0);
tie(e,flag) = add_edge(2, 5, G);
ds.union_set(2,5);
cout &lt;&lt; "An undirected graph:" &lt;&lt; endl;
print_graph(G, get(vertex_index, G));
cout &lt;&lt; endl;
Graph::vertex_iterator i,end;
for (tie(i,end) = vertices(G); i != end; ++i)
cout &lt;&lt; "representative[" &lt;&lt; *i &lt;&lt; "] = " &lt;&lt;
ds.find_set(*i) &lt;&lt; endl;;
cout &lt;&lt; endl;
typedef component_index&lt;int&gt; Components;
Components components(parent.begin(), parent.end());
for (Components::size_type i = 0; i &lt; components.size(); ++i) {
cout &lt;&lt; "component " &lt;&lt; i &lt;&lt; " contains: ";
Components::value_type::iterator
j = components[i].begin(),
jend = components[i].end();
for ( ; j != jend; ++j)
cout &lt;&lt; *j &lt;&lt; " ";
cout &lt;&lt; endl;
}
</PRE>
<P>
<hr>
<p>
<H2><A NAME="sec:initialize-dynamic-components"></A>
<TT>initialize_dynamic_components</TT>
</H2>
<P>
<DIV ALIGN="left">
<TABLE CELLPADDING=3 border>
<TR><TH ALIGN="LEFT"><B>Graphs:</B></TH>
<TD ALIGN="LEFT">undirected</TD>
</TR>
<TR><TH ALIGN="LEFT"><B>Properties:</B></TH>
<TD ALIGN="LEFT">rank, parent (in disjoint-sets)</TD>
</TR>
<TR><TH ALIGN="LEFT"><B>Complexity:</B></TH>
<TD></TD>
</TR>
</TABLE>
</DIV>
<P>
<PRE>
template &lt;class VertexListGraph, class DisjointSets&gt;
void initialize_dynamic_components(VertexListGraph&amp; G, DisjointSets&amp; ds)
</PRE>
<P>
This prepares the disjoint-sets data structure for the dynamic
connected components algorithm by making each vertex in the graph a
member of its own component (or set).
<P>
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/connected_components.hpp"><TT>boost/graph/connected_components.hpp</TT></a>
<p>
<hr>
<P>
<H2><A NAME="sec:dynamic-connected-components"></A>
<TT>dynamic_connected_components</TT>
</H2>
<P>
<DIV ALIGN="left">
<TABLE CELLPADDING=3 border>
<TR><TH ALIGN="LEFT"><B>Graphs:</B></TH>
<TD ALIGN="LEFT">undirected</TD>
</TR>
<TR><TH ALIGN="LEFT"><B>Properties:</B></TH>
<TD ALIGN="LEFT">rank, parent (in disjoint-sets)</TD>
</TR>
<TR><TH ALIGN="LEFT"><B>Complexity:</B></TH>
<TD ALIGN="LEFT"><i>O(E)</i></TD>
</TR>
</TABLE>
</DIV>
<p>
<PRE>
template &lt;class EdgeListGraph, class DisjointSets&gt;
void dynamic_connected_components(EdgeListGraph&amp; g, DisjointSets&amp; ds)
</PRE>
<P>
This function calculates the connected components of the graph,
embedding the results in the disjoint-sets data structure.
<P>
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/connected_components.hpp"><TT>boost/graph/connected_components.hpp</TT></a>
<P>
<H3>Requirements on Types</H3>
<P>
<UL>
<LI>The graph type must be a model of <a href="./EdgeListGraph.html">EdgeListGraph</a>.
</LI>
</UL>
<P>
<hr>
<p>
<H2><A NAME="sec:same-component">
<TT>same_component</TT></A>
</H2>
<P>
<DIV ALIGN="left">
<TABLE CELLPADDING=3 border>
<TR><TH ALIGN="LEFT"><B>Properties:</B></TH>
<TD ALIGN="LEFT">rank, parent (in disjoint-sets)</TD>
</TR>
<TR><TH ALIGN="LEFT"><B>Complexity:</B></TH>
<TD ALIGN="LEFT"><i>O(alpha(E,V))</i></TD>
</TR>
</TABLE>
</DIV>
<P>
<PRE>
template &lt;class Vertex, class DisjointSet&gt;
bool same_component(Vertex u, Vertex v, DisjointSet&amp; ds)
</PRE>
<P>
This function determines whether <TT>u</TT> and <TT>v</TT> are in the same
component.
<P>
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/connected_components.hpp"><TT>boost/graph/connected_components.hpp</TT></a>
<P>
<H3>Requirements on Types</H3>
<P>
<UL>
<LI><TT>Vertex</TT> must be compatible with the rank and parent
property maps of the <TT>DisjointSets</TT> data structure.
</LI>
</UL>
<P>
<hr>
<p>
<H2><A NAME="sec:component-index"></A>
<TT>component_index</TT>
</H2>
<p>
<PRE>
component_index&lt;Index&gt;
</PRE>
<P>
The is a class that provides an STL container-like view for the
components of the graph. Each component is a container-like object,
and the <TT>component_index</TT> object provides access to the
component objects via <TT>operator[]</TT>. A <TT>component_index</TT>
object is initialized with the parents property in the disjoint-sets
calculated from the <TT>dynamic_connected_components()</TT> function.
<P>
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/connected_components.hpp"><TT>boost/graph/connected_components.hpp</TT></a>
<P>
<H3>Members</H3>
<P>
<table border>
<tr>
<th>Member</th> <th>Description</th>
</tr>
<tr>
<td><tt>size_type</tt></td>
<td>The type used for representing the number of components.</td>
</tr>
<tr>
<td><tt>value_type</tt></td>
<td>
The type for a component object. The component type has the following members.
</td>
</tr>
<tr>
<td><tt>value_type::value_type</tt></td>
<td>
The value type of a component object is a vertex ID.
</td>
</tr>
<tr>
<td><tt>value_type::iterator</tt></td>
<td>
This iterator can be used to traverse all of the vertices
in the component. This iterator dereferences to give a vertex ID.
</td>
</tr>
<tr>
<td><tt>value_type::const_iterator</tt></td>
<td>
The const iterator.
</td>
</tr>
<tr>
<td><tt>value_type::iterator value_type::begin() const</tt></td>
<td>
Return an iterator pointing to the first vertex in the component.
</td>
</tr>
<tr>
<td><tt>value_type::iterator value_type::end() const</tt></td>
<td>
Return an iterator pointing past the end of the last vertex in the
component.
</td>
<tr>
<tr>
<td>
<tt>
template &lt;class ComponentsContainer&gt;
component_index(const ComponentsContainer&amp; c)
</tt>
</td>
<td>
Construct the <TT>component_index</TT> using the information
from the components container <TT>c</TT> which was the result
of executing <TT>connected_components_on_edgelist</TT>.
</td>
</tr>
<tr>
<td><tt>value_type operator[](size_type i)</tt></td>
<td>
Returns the <TT>i</TT>th component in the graph.
</td>
</tr>
<tr>
<td><tt>size_type component_index::size()</tt></td>
<td>
Returns the number of components in the graph.
</td>
</table>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../../people/jeremy_siek.htm">Jeremy Siek</A>,
Univ.of Notre Dame (<A
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
<A HREF="../../../people/liequan_lee.htm">Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
<A HREF=http://www.lsc.nd.edu/~lums>Andrew Lumsdaine</A>,
Univ.of Notre Dame (<A
HREF="mailto:lums@lsc.nd.edu">lums@lsc.nd.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>