strong_components.w 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. \documentclass[11pt]{report}
  2. \input{defs}
  3. \setlength\overfullrule{5pt}
  4. \tolerance=10000
  5. \sloppy
  6. \hfuzz=10pt
  7. \makeindex
  8. \begin{document}
  9. \title{A Generic Programming Implementation of Strongly Connected Components}
  10. \author{Jeremy G. Siek}
  11. \maketitle
  12. \section{Introduction}
  13. This paper describes the implementation of the
  14. \code{strong\_components()} function of the Boost Graph Library. The
  15. function computes the strongly connects components of a directed graph
  16. using Tarjan's DFS-based
  17. algorithm~\cite{tarjan72:dfs_and_linear_algo}.
  18. A \keyword{strongly connected component} (SCC) of a directed graph
  19. $G=(V,E)$ is a maximal set of vertices $U$ which is in $V$ such that
  20. for every pair of vertices $u$ and $v$ in $U$, we have both a path
  21. from $u$ to $v$ and path from $v$ to $u$. That is to say that $u$ and
  22. $v$ are reachable from each other.
  23. cross edge (u,v) is an edge from one subtree to another subtree
  24. -> discover_time[u] > discover_time[v]
  25. Lemma 10. Let $v$ and $w$ be vertices in $G$ which are in the same
  26. SCC and let $F$ be any depth-first forest of $G$. Then $v$ and $w$
  27. have a common ancestor in $F$. Also, if $u$ is the common ancestor of
  28. $u$ and $v$ with the latest discover time then $w$ is also in the same
  29. SCC as $u$ and $v$.
  30. Proof.
  31. If there is a path from $v$ to $w$ and if they are in different DFS
  32. trees, then the discover time for $w$ must be earlier than for $v$.
  33. Otherwise, the tree that contains $v$ would have extended along the
  34. path to $w$, putting $v$ and $w$ in the same tree.
  35. The following is an informal description of Tarjan's algorithm for
  36. computing strongly connected components. It is basically a variation
  37. on depth-first search, with extra actions being taken at the
  38. ``discover vertex'' and ``finish vertex'' event points. It may help to
  39. think of the actions taken at the ``discover vertex'' event point as
  40. occuring ``on the way down'' a DFS-tree (from the root towards the
  41. leaves), and actions taken a the ``finish vertex'' event point as
  42. occuring ``on the way back up''.
  43. There are three things that need to happen on the way down. For each
  44. vertex $u$ visited we record the discover time $d[u]$, push vertex $u$
  45. onto a auxiliary stack, and set $root[u] = u$. The root field will
  46. end up mapping each vertex to the topmost vertex in the same strongly
  47. connected component. By setting $root[u] = u$ we are starting with
  48. each vertex in a component by itself.
  49. Now to describe what happens on the way back up. Suppose we have just
  50. finished visiting all of the vertices adjacent to some vertex $u$. We
  51. then scan each of the adjacent vertices again, checking the root of
  52. each for which one has the earliest discover time, which we will call
  53. root $a$. We then compare $a$ with vertex $u$ and consider the
  54. following cases:
  55. \begin{enumerate}
  56. \item If $d[a] < d[u]$ then we know that $a$ is really an ancestor of
  57. $u$ in the DFS tree and therefore we have a cycle and $u$ must be in
  58. a SCC with $a$. We then set $root[u] = a$ and continue our way back up
  59. the DFS.
  60. \item If $a = u$ then we know that $u$ must be the topmost vertex of a
  61. subtree that defines a SCC. All of the vertices in this subtree are
  62. further down on the stack than vertex $u$ so we pop the vertices off
  63. of the stack until we reach $u$ and mark each one as being in the
  64. same component.
  65. \item If $d[a] > d[u]$ then the adjacent vertices are in different
  66. strongly connected components. We continue our way back up the
  67. DFS.
  68. \end{enumerate}
  69. @d Build a list of vertices for each strongly connected component
  70. @{
  71. template <typename Graph, typename ComponentMap, typename ComponentLists>
  72. void build_component_lists
  73. (const Graph& g,
  74. typename graph_traits<Graph>::vertices_size_type num_scc,
  75. ComponentMap component_number,
  76. ComponentLists& components)
  77. {
  78. components.resize(num_scc);
  79. typename graph_traits<Graph>::vertex_iterator vi, vi_end;
  80. for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  81. components[component_number[*vi]].push_back(*vi);
  82. }
  83. @}
  84. \bibliographystyle{abbrv}
  85. \bibliography{jtran,ggcl,optimization,generic-programming,cad}
  86. \end{document}