undirected_dfs.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //
  2. //=======================================================================
  3. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  4. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //=======================================================================
  10. //
  11. #ifndef BOOST_GRAPH_UNDIRECTED_DFS_HPP
  12. #define BOOST_GRAPH_UNDIRECTED_DFS_HPP
  13. #include <boost/graph/depth_first_search.hpp>
  14. #include <vector>
  15. #include <boost/concept/assert.hpp>
  16. namespace boost
  17. {
  18. namespace detail
  19. {
  20. // Define BOOST_RECURSIVE_DFS to use older, recursive version.
  21. // It is retained for a while in order to perform performance
  22. // comparison.
  23. #ifndef BOOST_RECURSIVE_DFS
  24. template < typename IncidenceGraph, typename DFSVisitor,
  25. typename VertexColorMap, typename EdgeColorMap >
  26. void undir_dfv_impl(const IncidenceGraph& g,
  27. typename graph_traits< IncidenceGraph >::vertex_descriptor u,
  28. DFSVisitor& vis, VertexColorMap vertex_color, EdgeColorMap edge_color)
  29. {
  30. BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< IncidenceGraph >));
  31. BOOST_CONCEPT_ASSERT((DFSVisitorConcept< DFSVisitor, IncidenceGraph >));
  32. typedef
  33. typename graph_traits< IncidenceGraph >::vertex_descriptor Vertex;
  34. typedef typename graph_traits< IncidenceGraph >::edge_descriptor Edge;
  35. BOOST_CONCEPT_ASSERT(
  36. (ReadWritePropertyMapConcept< VertexColorMap, Vertex >));
  37. BOOST_CONCEPT_ASSERT(
  38. (ReadWritePropertyMapConcept< EdgeColorMap, Edge >));
  39. typedef
  40. typename property_traits< VertexColorMap >::value_type ColorValue;
  41. typedef
  42. typename property_traits< EdgeColorMap >::value_type EColorValue;
  43. BOOST_CONCEPT_ASSERT((ColorValueConcept< ColorValue >));
  44. BOOST_CONCEPT_ASSERT((ColorValueConcept< EColorValue >));
  45. typedef color_traits< ColorValue > Color;
  46. typedef color_traits< EColorValue > EColor;
  47. typedef typename graph_traits< IncidenceGraph >::out_edge_iterator Iter;
  48. typedef std::pair< Vertex,
  49. std::pair< boost::optional< Edge >, std::pair< Iter, Iter > > >
  50. VertexInfo;
  51. std::vector< VertexInfo > stack;
  52. put(vertex_color, u, Color::gray());
  53. vis.discover_vertex(u, g);
  54. stack.push_back(std::make_pair(
  55. u, std::make_pair(boost::optional< Edge >(), out_edges(u, g))));
  56. while (!stack.empty())
  57. {
  58. VertexInfo& back = stack.back();
  59. u = back.first;
  60. boost::optional< Edge > src_e = back.second.first;
  61. Iter ei = back.second.second.first,
  62. ei_end = back.second.second.second;
  63. stack.pop_back();
  64. while (ei != ei_end)
  65. {
  66. Vertex v = target(*ei, g);
  67. vis.examine_edge(*ei, g);
  68. ColorValue v_color = get(vertex_color, v);
  69. EColorValue uv_color = get(edge_color, *ei);
  70. put(edge_color, *ei, EColor::black());
  71. if (v_color == Color::white())
  72. {
  73. vis.tree_edge(*ei, g);
  74. src_e = *ei;
  75. stack.push_back(std::make_pair(u,
  76. std::make_pair(src_e, std::make_pair(++ei, ei_end))));
  77. u = v;
  78. put(vertex_color, u, Color::gray());
  79. vis.discover_vertex(u, g);
  80. boost::tie(ei, ei_end) = out_edges(u, g);
  81. }
  82. else if (v_color == Color::gray())
  83. {
  84. if (uv_color == EColor::white())
  85. vis.back_edge(*ei, g);
  86. call_finish_edge(vis, *ei, g);
  87. ++ei;
  88. }
  89. else
  90. { // if (v_color == Color::black())
  91. call_finish_edge(vis, *ei, g);
  92. ++ei;
  93. }
  94. }
  95. put(vertex_color, u, Color::black());
  96. vis.finish_vertex(u, g);
  97. if (src_e)
  98. call_finish_edge(vis, src_e.get(), g);
  99. }
  100. }
  101. #else // BOOST_RECURSIVE_DFS
  102. template < typename IncidenceGraph, typename DFSVisitor,
  103. typename VertexColorMap, typename EdgeColorMap >
  104. void undir_dfv_impl(const IncidenceGraph& g,
  105. typename graph_traits< IncidenceGraph >::vertex_descriptor u,
  106. DFSVisitor& vis, // pass-by-reference here, important!
  107. VertexColorMap vertex_color, EdgeColorMap edge_color)
  108. {
  109. BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< IncidenceGraph >));
  110. BOOST_CONCEPT_ASSERT((DFSVisitorConcept< DFSVisitor, IncidenceGraph >));
  111. typedef
  112. typename graph_traits< IncidenceGraph >::vertex_descriptor Vertex;
  113. typedef typename graph_traits< IncidenceGraph >::edge_descriptor Edge;
  114. BOOST_CONCEPT_ASSERT(
  115. (ReadWritePropertyMapConcept< VertexColorMap, Vertex >));
  116. BOOST_CONCEPT_ASSERT(
  117. (ReadWritePropertyMapConcept< EdgeColorMap, Edge >));
  118. typedef
  119. typename property_traits< VertexColorMap >::value_type ColorValue;
  120. typedef
  121. typename property_traits< EdgeColorMap >::value_type EColorValue;
  122. BOOST_CONCEPT_ASSERT((ColorValueConcept< ColorValue >));
  123. BOOST_CONCEPT_ASSERT((ColorValueConcept< EColorValue >));
  124. typedef color_traits< ColorValue > Color;
  125. typedef color_traits< EColorValue > EColor;
  126. typename graph_traits< IncidenceGraph >::out_edge_iterator ei, ei_end;
  127. put(vertex_color, u, Color::gray());
  128. vis.discover_vertex(u, g);
  129. for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei)
  130. {
  131. Vertex v = target(*ei, g);
  132. vis.examine_edge(*ei, g);
  133. ColorValue v_color = get(vertex_color, v);
  134. EColorValue uv_color = get(edge_color, *ei);
  135. put(edge_color, *ei, EColor::black());
  136. if (v_color == Color::white())
  137. {
  138. vis.tree_edge(*ei, g);
  139. undir_dfv_impl(g, v, vis, vertex_color, edge_color);
  140. }
  141. else if (v_color == Color::gray() && uv_color == EColor::white())
  142. vis.back_edge(*ei, g);
  143. call_finish_edge(vis, *ei, g);
  144. }
  145. put(vertex_color, u, Color::black());
  146. vis.finish_vertex(u, g);
  147. }
  148. #endif // ! BOOST_RECURSIVE_DFS
  149. } // namespace detail
  150. template < typename Graph, typename DFSVisitor, typename VertexColorMap,
  151. typename EdgeColorMap, typename Vertex >
  152. void undirected_dfs(const Graph& g, DFSVisitor vis, VertexColorMap vertex_color,
  153. EdgeColorMap edge_color, Vertex start_vertex)
  154. {
  155. BOOST_CONCEPT_ASSERT((DFSVisitorConcept< DFSVisitor, Graph >));
  156. BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph >));
  157. typedef typename property_traits< VertexColorMap >::value_type ColorValue;
  158. typedef color_traits< ColorValue > Color;
  159. typename graph_traits< Graph >::vertex_iterator ui, ui_end;
  160. for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
  161. {
  162. put(vertex_color, *ui, Color::white());
  163. vis.initialize_vertex(*ui, g);
  164. }
  165. typename graph_traits< Graph >::edge_iterator ei, ei_end;
  166. for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
  167. put(edge_color, *ei, Color::white());
  168. if (start_vertex != *vertices(g).first)
  169. {
  170. vis.start_vertex(start_vertex, g);
  171. detail::undir_dfv_impl(g, start_vertex, vis, vertex_color, edge_color);
  172. }
  173. for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
  174. {
  175. ColorValue u_color = get(vertex_color, *ui);
  176. if (u_color == Color::white())
  177. {
  178. vis.start_vertex(*ui, g);
  179. detail::undir_dfv_impl(g, *ui, vis, vertex_color, edge_color);
  180. }
  181. }
  182. }
  183. template < typename Graph, typename DFSVisitor, typename VertexColorMap,
  184. typename EdgeColorMap >
  185. void undirected_dfs(const Graph& g, DFSVisitor vis, VertexColorMap vertex_color,
  186. EdgeColorMap edge_color)
  187. {
  188. undirected_dfs(g, vis, vertex_color, edge_color, *vertices(g).first);
  189. }
  190. namespace detail
  191. {
  192. template < typename VertexColorMap > struct udfs_dispatch
  193. {
  194. template < typename Graph, typename Vertex, typename DFSVisitor,
  195. typename EdgeColorMap, typename P, typename T, typename R >
  196. static void apply(const Graph& g, DFSVisitor vis, Vertex start_vertex,
  197. const bgl_named_params< P, T, R >&, EdgeColorMap edge_color,
  198. VertexColorMap vertex_color)
  199. {
  200. undirected_dfs(g, vis, vertex_color, edge_color, start_vertex);
  201. }
  202. };
  203. template <> struct udfs_dispatch< param_not_found >
  204. {
  205. template < typename Graph, typename Vertex, typename DFSVisitor,
  206. typename EdgeColorMap, typename P, typename T, typename R >
  207. static void apply(const Graph& g, DFSVisitor vis, Vertex start_vertex,
  208. const bgl_named_params< P, T, R >& params, EdgeColorMap edge_color,
  209. param_not_found)
  210. {
  211. std::vector< default_color_type > color_vec(num_vertices(g));
  212. default_color_type c = white_color; // avoid warning about un-init
  213. undirected_dfs(g, vis,
  214. make_iterator_property_map(color_vec.begin(),
  215. choose_const_pmap(
  216. get_param(params, vertex_index), g, vertex_index),
  217. c),
  218. edge_color, start_vertex);
  219. }
  220. };
  221. } // namespace detail
  222. // Named Parameter Variant
  223. template < typename Graph, typename P, typename T, typename R >
  224. void undirected_dfs(const Graph& g, const bgl_named_params< P, T, R >& params)
  225. {
  226. typedef typename get_param_type< vertex_color_t,
  227. bgl_named_params< P, T, R > >::type C;
  228. detail::udfs_dispatch< C >::apply(g,
  229. choose_param(
  230. get_param(params, graph_visitor), make_dfs_visitor(null_visitor())),
  231. choose_param(get_param(params, root_vertex_t()), *vertices(g).first),
  232. params, get_param(params, edge_color), get_param(params, vertex_color));
  233. }
  234. template < typename IncidenceGraph, typename DFSVisitor,
  235. typename VertexColorMap, typename EdgeColorMap >
  236. void undirected_depth_first_visit(const IncidenceGraph& g,
  237. typename graph_traits< IncidenceGraph >::vertex_descriptor u,
  238. DFSVisitor vis, VertexColorMap vertex_color, EdgeColorMap edge_color)
  239. {
  240. detail::undir_dfv_impl(g, u, vis, vertex_color, edge_color);
  241. }
  242. } // namespace boost
  243. #endif