williamr@2
|
1 |
//=======================================================================
|
williamr@2
|
2 |
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
williamr@2
|
3 |
// Copyright 2003 Bruce Barr
|
williamr@2
|
4 |
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
williamr@2
|
5 |
//
|
williamr@2
|
6 |
// Distributed under the Boost Software License, Version 1.0. (See
|
williamr@2
|
7 |
// accompanying file LICENSE_1_0.txt or copy at
|
williamr@2
|
8 |
// http://www.boost.org/LICENSE_1_0.txt)
|
williamr@2
|
9 |
//=======================================================================
|
williamr@2
|
10 |
|
williamr@2
|
11 |
// Nonrecursive implementation of depth_first_visit_impl submitted by
|
williamr@2
|
12 |
// Bruce Barr, schmoost <at> yahoo.com, May/June 2003.
|
williamr@2
|
13 |
#ifndef BOOST_GRAPH_RECURSIVE_DFS_HPP
|
williamr@2
|
14 |
#define BOOST_GRAPH_RECURSIVE_DFS_HPP
|
williamr@2
|
15 |
|
williamr@2
|
16 |
#include <boost/config.hpp>
|
williamr@2
|
17 |
#include <boost/graph/graph_traits.hpp>
|
williamr@2
|
18 |
#include <boost/graph/graph_concepts.hpp>
|
williamr@2
|
19 |
#include <boost/graph/properties.hpp>
|
williamr@2
|
20 |
#include <boost/graph/visitors.hpp>
|
williamr@2
|
21 |
#include <boost/graph/named_function_params.hpp>
|
williamr@2
|
22 |
|
williamr@2
|
23 |
#include <boost/ref.hpp>
|
williamr@2
|
24 |
#include <boost/implicit_cast.hpp>
|
williamr@2
|
25 |
|
williamr@2
|
26 |
#include <vector>
|
williamr@2
|
27 |
#include <utility>
|
williamr@2
|
28 |
|
williamr@2
|
29 |
namespace boost {
|
williamr@2
|
30 |
|
williamr@2
|
31 |
template <class Visitor, class Graph>
|
williamr@2
|
32 |
class DFSVisitorConcept {
|
williamr@2
|
33 |
public:
|
williamr@2
|
34 |
void constraints() {
|
williamr@2
|
35 |
function_requires< CopyConstructibleConcept<Visitor> >();
|
williamr@2
|
36 |
vis.initialize_vertex(u, g);
|
williamr@2
|
37 |
vis.start_vertex(u, g);
|
williamr@2
|
38 |
vis.discover_vertex(u, g);
|
williamr@2
|
39 |
vis.examine_edge(e, g);
|
williamr@2
|
40 |
vis.tree_edge(e, g);
|
williamr@2
|
41 |
vis.back_edge(e, g);
|
williamr@2
|
42 |
vis.forward_or_cross_edge(e, g);
|
williamr@2
|
43 |
vis.finish_vertex(u, g);
|
williamr@2
|
44 |
}
|
williamr@2
|
45 |
private:
|
williamr@2
|
46 |
Visitor vis;
|
williamr@2
|
47 |
Graph g;
|
williamr@2
|
48 |
typename graph_traits<Graph>::vertex_descriptor u;
|
williamr@2
|
49 |
typename graph_traits<Graph>::edge_descriptor e;
|
williamr@2
|
50 |
};
|
williamr@2
|
51 |
|
williamr@2
|
52 |
namespace detail {
|
williamr@2
|
53 |
|
williamr@2
|
54 |
struct nontruth2 {
|
williamr@2
|
55 |
template<class T, class T2>
|
williamr@2
|
56 |
bool operator()(const T&, const T2&) const { return false; }
|
williamr@2
|
57 |
};
|
williamr@2
|
58 |
|
williamr@2
|
59 |
|
williamr@2
|
60 |
// Define BOOST_RECURSIVE_DFS to use older, recursive version.
|
williamr@2
|
61 |
// It is retained for a while in order to perform performance
|
williamr@2
|
62 |
// comparison.
|
williamr@2
|
63 |
#ifndef BOOST_RECURSIVE_DFS
|
williamr@2
|
64 |
|
williamr@2
|
65 |
// If the vertex u and the iterators ei and ei_end are thought of as the
|
williamr@2
|
66 |
// context of the algorithm, each push and pop from the stack could
|
williamr@2
|
67 |
// be thought of as a context shift.
|
williamr@2
|
68 |
// Each pass through "while (ei != ei_end)" may refer to the out-edges of
|
williamr@2
|
69 |
// an entirely different vertex, because the context of the algorithm
|
williamr@2
|
70 |
// shifts every time a white adjacent vertex is discovered.
|
williamr@2
|
71 |
// The corresponding context shift back from the adjacent vertex occurs
|
williamr@2
|
72 |
// after all of its out-edges have been examined.
|
williamr@2
|
73 |
//
|
williamr@2
|
74 |
// See http://lists.boost.org/MailArchives/boost/msg48752.php for FAQ.
|
williamr@2
|
75 |
|
williamr@2
|
76 |
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
|
williamr@2
|
77 |
class TerminatorFunc>
|
williamr@2
|
78 |
void depth_first_visit_impl
|
williamr@2
|
79 |
(const IncidenceGraph& g,
|
williamr@2
|
80 |
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
williamr@2
|
81 |
DFSVisitor& vis,
|
williamr@2
|
82 |
ColorMap color, TerminatorFunc func = TerminatorFunc())
|
williamr@2
|
83 |
{
|
williamr@2
|
84 |
function_requires<IncidenceGraphConcept<IncidenceGraph> >();
|
williamr@2
|
85 |
function_requires<DFSVisitorConcept<DFSVisitor, IncidenceGraph> >();
|
williamr@2
|
86 |
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
williamr@2
|
87 |
function_requires< ReadWritePropertyMapConcept<ColorMap, Vertex> >();
|
williamr@2
|
88 |
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
williamr@2
|
89 |
function_requires< ColorValueConcept<ColorValue> >();
|
williamr@2
|
90 |
typedef color_traits<ColorValue> Color;
|
williamr@2
|
91 |
typedef typename graph_traits<IncidenceGraph>::out_edge_iterator Iter;
|
williamr@2
|
92 |
typedef std::pair<Vertex, std::pair<Iter, Iter> > VertexInfo;
|
williamr@2
|
93 |
|
williamr@2
|
94 |
Iter ei, ei_end;
|
williamr@2
|
95 |
std::vector<VertexInfo> stack;
|
williamr@2
|
96 |
|
williamr@2
|
97 |
// Possible optimization for vector
|
williamr@2
|
98 |
//stack.reserve(num_vertices(g));
|
williamr@2
|
99 |
|
williamr@2
|
100 |
typedef typename unwrap_reference<TerminatorFunc>::type TF;
|
williamr@2
|
101 |
|
williamr@2
|
102 |
put(color, u, Color::gray());
|
williamr@2
|
103 |
vis.discover_vertex(u, g);
|
williamr@2
|
104 |
tie(ei, ei_end) = out_edges(u, g);
|
williamr@2
|
105 |
// Variable is needed to workaround a borland bug.
|
williamr@2
|
106 |
TF& fn = static_cast<TF&>(func);
|
williamr@2
|
107 |
if (fn(u, g)) {
|
williamr@2
|
108 |
// If this vertex terminates the search, we push empty range
|
williamr@2
|
109 |
stack.push_back(std::make_pair(u, std::make_pair(ei_end, ei_end)));
|
williamr@2
|
110 |
} else {
|
williamr@2
|
111 |
stack.push_back(std::make_pair(u, std::make_pair(ei, ei_end)));
|
williamr@2
|
112 |
}
|
williamr@2
|
113 |
while (!stack.empty()) {
|
williamr@2
|
114 |
VertexInfo& back = stack.back();
|
williamr@2
|
115 |
u = back.first;
|
williamr@2
|
116 |
tie(ei, ei_end) = back.second;
|
williamr@2
|
117 |
stack.pop_back();
|
williamr@2
|
118 |
while (ei != ei_end) {
|
williamr@2
|
119 |
Vertex v = target(*ei, g);
|
williamr@2
|
120 |
vis.examine_edge(*ei, g);
|
williamr@2
|
121 |
ColorValue v_color = get(color, v);
|
williamr@2
|
122 |
if (v_color == Color::white()) {
|
williamr@2
|
123 |
vis.tree_edge(*ei, g);
|
williamr@2
|
124 |
stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end)));
|
williamr@2
|
125 |
u = v;
|
williamr@2
|
126 |
put(color, u, Color::gray());
|
williamr@2
|
127 |
vis.discover_vertex(u, g);
|
williamr@2
|
128 |
tie(ei, ei_end) = out_edges(u, g);
|
williamr@2
|
129 |
if (fn(u, g)) {
|
williamr@2
|
130 |
ei = ei_end;
|
williamr@2
|
131 |
}
|
williamr@2
|
132 |
} else if (v_color == Color::gray()) {
|
williamr@2
|
133 |
vis.back_edge(*ei, g);
|
williamr@2
|
134 |
++ei;
|
williamr@2
|
135 |
} else {
|
williamr@2
|
136 |
vis.forward_or_cross_edge(*ei, g);
|
williamr@2
|
137 |
++ei;
|
williamr@2
|
138 |
}
|
williamr@2
|
139 |
}
|
williamr@2
|
140 |
put(color, u, Color::black());
|
williamr@2
|
141 |
vis.finish_vertex(u, g);
|
williamr@2
|
142 |
}
|
williamr@2
|
143 |
}
|
williamr@2
|
144 |
|
williamr@2
|
145 |
#else // BOOST_RECURSIVE_DFS is defined
|
williamr@2
|
146 |
|
williamr@2
|
147 |
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
|
williamr@2
|
148 |
class TerminatorFunc>
|
williamr@2
|
149 |
void depth_first_visit_impl
|
williamr@2
|
150 |
(const IncidenceGraph& g,
|
williamr@2
|
151 |
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
williamr@2
|
152 |
DFSVisitor& vis, // pass-by-reference here, important!
|
williamr@2
|
153 |
ColorMap color, TerminatorFunc func)
|
williamr@2
|
154 |
{
|
williamr@2
|
155 |
function_requires<IncidenceGraphConcept<IncidenceGraph> >();
|
williamr@2
|
156 |
function_requires<DFSVisitorConcept<DFSVisitor, IncidenceGraph> >();
|
williamr@2
|
157 |
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
williamr@2
|
158 |
function_requires< ReadWritePropertyMapConcept<ColorMap, Vertex> >();
|
williamr@2
|
159 |
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
williamr@2
|
160 |
function_requires< ColorValueConcept<ColorValue> >();
|
williamr@2
|
161 |
typedef color_traits<ColorValue> Color;
|
williamr@2
|
162 |
typename graph_traits<IncidenceGraph>::out_edge_iterator ei, ei_end;
|
williamr@2
|
163 |
|
williamr@2
|
164 |
put(color, u, Color::gray()); vis.discover_vertex(u, g);
|
williamr@2
|
165 |
|
williamr@2
|
166 |
typedef typename unwrap_reference<TerminatorFunc>::type TF;
|
williamr@2
|
167 |
// Variable is needed to workaround a borland bug.
|
williamr@2
|
168 |
TF& fn = static_cast<TF&>(func);
|
williamr@2
|
169 |
if (!fn(u, g))
|
williamr@2
|
170 |
for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
|
williamr@2
|
171 |
Vertex v = target(*ei, g); vis.examine_edge(*ei, g);
|
williamr@2
|
172 |
ColorValue v_color = get(color, v);
|
williamr@2
|
173 |
if (v_color == Color::white()) { vis.tree_edge(*ei, g);
|
williamr@2
|
174 |
depth_first_visit_impl(g, v, vis, color, func);
|
williamr@2
|
175 |
} else if (v_color == Color::gray()) vis.back_edge(*ei, g);
|
williamr@2
|
176 |
else vis.forward_or_cross_edge(*ei, g);
|
williamr@2
|
177 |
}
|
williamr@2
|
178 |
put(color, u, Color::black()); vis.finish_vertex(u, g);
|
williamr@2
|
179 |
}
|
williamr@2
|
180 |
|
williamr@2
|
181 |
#endif
|
williamr@2
|
182 |
|
williamr@2
|
183 |
} // namespace detail
|
williamr@2
|
184 |
|
williamr@2
|
185 |
template <class VertexListGraph, class DFSVisitor, class ColorMap>
|
williamr@2
|
186 |
void
|
williamr@2
|
187 |
depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color,
|
williamr@2
|
188 |
typename graph_traits<VertexListGraph>::vertex_descriptor start_vertex)
|
williamr@2
|
189 |
{
|
williamr@2
|
190 |
typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
|
williamr@2
|
191 |
function_requires<DFSVisitorConcept<DFSVisitor, VertexListGraph> >();
|
williamr@2
|
192 |
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
williamr@2
|
193 |
typedef color_traits<ColorValue> Color;
|
williamr@2
|
194 |
|
williamr@2
|
195 |
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
|
williamr@2
|
196 |
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
williamr@2
|
197 |
put(color, *ui, Color::white()); vis.initialize_vertex(*ui, g);
|
williamr@2
|
198 |
}
|
williamr@2
|
199 |
|
williamr@2
|
200 |
if (start_vertex != implicit_cast<Vertex>(*vertices(g).first)){ vis.start_vertex(start_vertex, g);
|
williamr@2
|
201 |
detail::depth_first_visit_impl(g, start_vertex, vis, color,
|
williamr@2
|
202 |
detail::nontruth2());
|
williamr@2
|
203 |
}
|
williamr@2
|
204 |
|
williamr@2
|
205 |
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
williamr@2
|
206 |
ColorValue u_color = get(color, *ui);
|
williamr@2
|
207 |
if (u_color == Color::white()) { vis.start_vertex(*ui, g);
|
williamr@2
|
208 |
detail::depth_first_visit_impl(g, *ui, vis, color, detail::nontruth2());
|
williamr@2
|
209 |
}
|
williamr@2
|
210 |
}
|
williamr@2
|
211 |
}
|
williamr@2
|
212 |
|
williamr@2
|
213 |
template <class VertexListGraph, class DFSVisitor, class ColorMap>
|
williamr@2
|
214 |
void
|
williamr@2
|
215 |
depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color)
|
williamr@2
|
216 |
{
|
williamr@2
|
217 |
if (vertices(g).first == vertices(g).second)
|
williamr@2
|
218 |
return;
|
williamr@2
|
219 |
|
williamr@2
|
220 |
depth_first_search(g, vis, color, *vertices(g).first);
|
williamr@2
|
221 |
}
|
williamr@2
|
222 |
|
williamr@2
|
223 |
namespace detail {
|
williamr@2
|
224 |
template <class ColorMap>
|
williamr@2
|
225 |
struct dfs_dispatch {
|
williamr@2
|
226 |
|
williamr@2
|
227 |
template <class VertexListGraph, class Vertex, class DFSVisitor,
|
williamr@2
|
228 |
class P, class T, class R>
|
williamr@2
|
229 |
static void
|
williamr@2
|
230 |
apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex,
|
williamr@2
|
231 |
const bgl_named_params<P, T, R>&,
|
williamr@2
|
232 |
ColorMap color)
|
williamr@2
|
233 |
{
|
williamr@2
|
234 |
depth_first_search(g, vis, color, start_vertex);
|
williamr@2
|
235 |
}
|
williamr@2
|
236 |
};
|
williamr@2
|
237 |
|
williamr@2
|
238 |
template <>
|
williamr@2
|
239 |
struct dfs_dispatch<detail::error_property_not_found> {
|
williamr@2
|
240 |
template <class VertexListGraph, class Vertex, class DFSVisitor,
|
williamr@2
|
241 |
class P, class T, class R>
|
williamr@2
|
242 |
static void
|
williamr@2
|
243 |
apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex,
|
williamr@2
|
244 |
const bgl_named_params<P, T, R>& params,
|
williamr@2
|
245 |
detail::error_property_not_found)
|
williamr@2
|
246 |
{
|
williamr@2
|
247 |
std::vector<default_color_type> color_vec(num_vertices(g));
|
williamr@2
|
248 |
default_color_type c = white_color; // avoid warning about un-init
|
williamr@2
|
249 |
depth_first_search
|
williamr@2
|
250 |
(g, vis, make_iterator_property_map
|
williamr@2
|
251 |
(color_vec.begin(),
|
williamr@2
|
252 |
choose_const_pmap(get_param(params, vertex_index),
|
williamr@2
|
253 |
g, vertex_index), c),
|
williamr@2
|
254 |
start_vertex);
|
williamr@2
|
255 |
}
|
williamr@2
|
256 |
};
|
williamr@2
|
257 |
} // namespace detail
|
williamr@2
|
258 |
|
williamr@2
|
259 |
|
williamr@2
|
260 |
template <class Visitors = null_visitor>
|
williamr@2
|
261 |
class dfs_visitor {
|
williamr@2
|
262 |
public:
|
williamr@2
|
263 |
dfs_visitor() { }
|
williamr@2
|
264 |
dfs_visitor(Visitors vis) : m_vis(vis) { }
|
williamr@2
|
265 |
|
williamr@2
|
266 |
template <class Vertex, class Graph>
|
williamr@2
|
267 |
void initialize_vertex(Vertex u, const Graph& g) {
|
williamr@2
|
268 |
invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex());
|
williamr@2
|
269 |
}
|
williamr@2
|
270 |
template <class Vertex, class Graph>
|
williamr@2
|
271 |
void start_vertex(Vertex u, const Graph& g) {
|
williamr@2
|
272 |
invoke_visitors(m_vis, u, g, ::boost::on_start_vertex());
|
williamr@2
|
273 |
}
|
williamr@2
|
274 |
template <class Vertex, class Graph>
|
williamr@2
|
275 |
void discover_vertex(Vertex u, const Graph& g) {
|
williamr@2
|
276 |
invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex());
|
williamr@2
|
277 |
}
|
williamr@2
|
278 |
template <class Edge, class Graph>
|
williamr@2
|
279 |
void examine_edge(Edge u, const Graph& g) {
|
williamr@2
|
280 |
invoke_visitors(m_vis, u, g, ::boost::on_examine_edge());
|
williamr@2
|
281 |
}
|
williamr@2
|
282 |
template <class Edge, class Graph>
|
williamr@2
|
283 |
void tree_edge(Edge u, const Graph& g) {
|
williamr@2
|
284 |
invoke_visitors(m_vis, u, g, ::boost::on_tree_edge());
|
williamr@2
|
285 |
}
|
williamr@2
|
286 |
template <class Edge, class Graph>
|
williamr@2
|
287 |
void back_edge(Edge u, const Graph& g) {
|
williamr@2
|
288 |
invoke_visitors(m_vis, u, g, ::boost::on_back_edge());
|
williamr@2
|
289 |
}
|
williamr@2
|
290 |
template <class Edge, class Graph>
|
williamr@2
|
291 |
void forward_or_cross_edge(Edge u, const Graph& g) {
|
williamr@2
|
292 |
invoke_visitors(m_vis, u, g, ::boost::on_forward_or_cross_edge());
|
williamr@2
|
293 |
}
|
williamr@2
|
294 |
template <class Vertex, class Graph>
|
williamr@2
|
295 |
void finish_vertex(Vertex u, const Graph& g) {
|
williamr@2
|
296 |
invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex());
|
williamr@2
|
297 |
}
|
williamr@2
|
298 |
|
williamr@2
|
299 |
BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,dfs)
|
williamr@2
|
300 |
BOOST_GRAPH_EVENT_STUB(on_start_vertex,dfs)
|
williamr@2
|
301 |
BOOST_GRAPH_EVENT_STUB(on_discover_vertex,dfs)
|
williamr@2
|
302 |
BOOST_GRAPH_EVENT_STUB(on_examine_edge,dfs)
|
williamr@2
|
303 |
BOOST_GRAPH_EVENT_STUB(on_tree_edge,dfs)
|
williamr@2
|
304 |
BOOST_GRAPH_EVENT_STUB(on_back_edge,dfs)
|
williamr@2
|
305 |
BOOST_GRAPH_EVENT_STUB(on_forward_or_cross_edge,dfs)
|
williamr@2
|
306 |
BOOST_GRAPH_EVENT_STUB(on_finish_vertex,dfs)
|
williamr@2
|
307 |
|
williamr@2
|
308 |
protected:
|
williamr@2
|
309 |
Visitors m_vis;
|
williamr@2
|
310 |
};
|
williamr@2
|
311 |
template <class Visitors>
|
williamr@2
|
312 |
dfs_visitor<Visitors>
|
williamr@2
|
313 |
make_dfs_visitor(Visitors vis) {
|
williamr@2
|
314 |
return dfs_visitor<Visitors>(vis);
|
williamr@2
|
315 |
}
|
williamr@2
|
316 |
typedef dfs_visitor<> default_dfs_visitor;
|
williamr@2
|
317 |
|
williamr@2
|
318 |
|
williamr@2
|
319 |
// Named Parameter Variant
|
williamr@2
|
320 |
template <class VertexListGraph, class P, class T, class R>
|
williamr@2
|
321 |
void
|
williamr@2
|
322 |
depth_first_search(const VertexListGraph& g,
|
williamr@2
|
323 |
const bgl_named_params<P, T, R>& params)
|
williamr@2
|
324 |
{
|
williamr@2
|
325 |
typedef typename property_value< bgl_named_params<P, T, R>,
|
williamr@2
|
326 |
vertex_color_t>::type C;
|
williamr@2
|
327 |
if (vertices(g).first == vertices(g).second)
|
williamr@2
|
328 |
return;
|
williamr@2
|
329 |
detail::dfs_dispatch<C>::apply
|
williamr@2
|
330 |
(g,
|
williamr@2
|
331 |
choose_param(get_param(params, graph_visitor),
|
williamr@2
|
332 |
make_dfs_visitor(null_visitor())),
|
williamr@2
|
333 |
choose_param(get_param(params, root_vertex_t()),
|
williamr@2
|
334 |
*vertices(g).first),
|
williamr@2
|
335 |
params,
|
williamr@2
|
336 |
get_param(params, vertex_color)
|
williamr@2
|
337 |
);
|
williamr@2
|
338 |
}
|
williamr@2
|
339 |
|
williamr@2
|
340 |
template <class IncidenceGraph, class DFSVisitor, class ColorMap>
|
williamr@2
|
341 |
void depth_first_visit
|
williamr@2
|
342 |
(const IncidenceGraph& g,
|
williamr@2
|
343 |
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
williamr@2
|
344 |
DFSVisitor vis, ColorMap color)
|
williamr@2
|
345 |
{
|
williamr@2
|
346 |
vis.start_vertex(u, g);
|
williamr@2
|
347 |
detail::depth_first_visit_impl(g, u, vis, color, detail::nontruth2());
|
williamr@2
|
348 |
}
|
williamr@2
|
349 |
|
williamr@2
|
350 |
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
|
williamr@2
|
351 |
class TerminatorFunc>
|
williamr@2
|
352 |
void depth_first_visit
|
williamr@2
|
353 |
(const IncidenceGraph& g,
|
williamr@2
|
354 |
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
williamr@2
|
355 |
DFSVisitor vis, ColorMap color, TerminatorFunc func = TerminatorFunc())
|
williamr@2
|
356 |
{
|
williamr@2
|
357 |
vis.start_vertex(u, g);
|
williamr@2
|
358 |
detail::depth_first_visit_impl(g, u, vis, color, func);
|
williamr@2
|
359 |
}
|
williamr@2
|
360 |
|
williamr@2
|
361 |
|
williamr@2
|
362 |
} // namespace boost
|
williamr@2
|
363 |
|
williamr@2
|
364 |
|
williamr@2
|
365 |
#endif
|