connected_components.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //=======================================================================
  2. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  3. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //=======================================================================
  9. #ifndef BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP
  10. #define BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP
  11. #if defined(__sgi) && !defined(__GNUC__)
  12. #pragma set woff 1234
  13. #endif
  14. #include <boost/operators.hpp>
  15. namespace boost
  16. {
  17. namespace detail
  18. {
  19. //=========================================================================
  20. // Implementation details of connected_components
  21. // This is used both in the connected_components algorithm and in
  22. // the kosaraju strong components algorithm during the second DFS
  23. // traversal.
  24. template < class ComponentsPA, class DFSVisitor >
  25. class components_recorder : public DFSVisitor
  26. {
  27. typedef typename property_traits< ComponentsPA >::value_type comp_type;
  28. public:
  29. components_recorder(ComponentsPA c, comp_type& c_count, DFSVisitor v)
  30. : DFSVisitor(v), m_component(c), m_count(c_count)
  31. {
  32. }
  33. template < class Vertex, class Graph >
  34. void start_vertex(Vertex u, Graph& g)
  35. {
  36. ++m_count;
  37. DFSVisitor::start_vertex(u, g);
  38. }
  39. template < class Vertex, class Graph >
  40. void discover_vertex(Vertex u, Graph& g)
  41. {
  42. put(m_component, u, m_count);
  43. DFSVisitor::discover_vertex(u, g);
  44. }
  45. protected:
  46. ComponentsPA m_component;
  47. comp_type& m_count;
  48. };
  49. template < class DiscoverTimeMap, class FinishTimeMap, class TimeT,
  50. class DFSVisitor >
  51. class time_recorder : public DFSVisitor
  52. {
  53. public:
  54. time_recorder(
  55. DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor v)
  56. : DFSVisitor(v), m_discover_time(d), m_finish_time(f), m_t(t)
  57. {
  58. }
  59. template < class Vertex, class Graph >
  60. void discover_vertex(Vertex u, Graph& g)
  61. {
  62. put(m_discover_time, u, ++m_t);
  63. DFSVisitor::discover_vertex(u, g);
  64. }
  65. template < class Vertex, class Graph >
  66. void finish_vertex(Vertex u, Graph& g)
  67. {
  68. put(m_finish_time, u, ++m_t);
  69. DFSVisitor::discover_vertex(u, g);
  70. }
  71. protected:
  72. DiscoverTimeMap m_discover_time;
  73. FinishTimeMap m_finish_time;
  74. TimeT m_t;
  75. };
  76. template < class DiscoverTimeMap, class FinishTimeMap, class TimeT,
  77. class DFSVisitor >
  78. time_recorder< DiscoverTimeMap, FinishTimeMap, TimeT, DFSVisitor >
  79. record_times(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor vis)
  80. {
  81. return time_recorder< DiscoverTimeMap, FinishTimeMap, TimeT,
  82. DFSVisitor >(d, f, t, vis);
  83. }
  84. //=========================================================================
  85. // Implementation detail of dynamic_components
  86. //-------------------------------------------------------------------------
  87. // Helper functions for the component_index class
  88. // Record the representative vertices in the header array.
  89. // Representative vertices now point to the component number.
  90. template < class Parent, class OutputIterator, class Integer >
  91. inline void build_components_header(
  92. Parent p, OutputIterator header, Integer num_nodes)
  93. {
  94. Parent component = p;
  95. Integer component_num = 0;
  96. for (Integer v = 0; v != num_nodes; ++v)
  97. if (p[v] == v)
  98. {
  99. *header++ = v;
  100. component[v] = component_num++;
  101. }
  102. }
  103. // Pushes x onto the front of the list. The list is represented in
  104. // an array.
  105. template < class Next, class T, class V >
  106. inline void push_front(Next next, T& head, V x)
  107. {
  108. T tmp = head;
  109. head = x;
  110. next[x] = tmp;
  111. }
  112. // Create a linked list of the vertices in each component
  113. // by reusing the representative array.
  114. template < class Parent1, class Parent2, class Integer >
  115. void link_components(Parent1 component, Parent2 header, Integer num_nodes,
  116. Integer num_components)
  117. {
  118. // Make the non-representative vertices point to their component
  119. Parent1 representative = component;
  120. for (Integer v = 0; v != num_nodes; ++v)
  121. if (component[v] >= num_components || header[component[v]] != v)
  122. component[v] = component[representative[v]];
  123. // initialize the "head" of the lists to "NULL"
  124. std::fill_n(header, num_components, num_nodes);
  125. // Add each vertex to the linked list for its component
  126. Parent1 next = component;
  127. for (Integer k = 0; k != num_nodes; ++k)
  128. push_front(next, header[component[k]], k);
  129. }
  130. template < class IndexContainer, class HeaderContainer >
  131. void construct_component_index(
  132. IndexContainer& index, HeaderContainer& header)
  133. {
  134. build_components_header(index.begin(), std::back_inserter(header),
  135. index.end() - index.begin());
  136. link_components(index.begin(), header.begin(),
  137. index.end() - index.begin(), header.end() - header.begin());
  138. }
  139. template < class IndexIterator, class Integer, class Distance >
  140. class component_iterator
  141. : boost::forward_iterator_helper<
  142. component_iterator< IndexIterator, Integer, Distance >, Integer,
  143. Distance, Integer*, Integer& >
  144. {
  145. public:
  146. typedef component_iterator self;
  147. IndexIterator next;
  148. Integer node;
  149. typedef std::forward_iterator_tag iterator_category;
  150. typedef Integer value_type;
  151. typedef Integer& reference;
  152. typedef Integer* pointer;
  153. typedef Distance difference_type;
  154. component_iterator() {}
  155. component_iterator(IndexIterator x, Integer i) : next(x), node(i) {}
  156. Integer operator*() const { return node; }
  157. self& operator++()
  158. {
  159. node = next[node];
  160. return *this;
  161. }
  162. };
  163. template < class IndexIterator, class Integer, class Distance >
  164. inline bool operator==(
  165. const component_iterator< IndexIterator, Integer, Distance >& x,
  166. const component_iterator< IndexIterator, Integer, Distance >& y)
  167. {
  168. return x.node == y.node;
  169. }
  170. } // namespace detail
  171. } // namespace detail
  172. #if defined(__sgi) && !defined(__GNUC__)
  173. #pragma reset woff 1234
  174. #endif
  175. #endif