Chris@16
|
1 // Copyright (C) 2012, Michele Caini.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
3 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 // Two Graphs Common Spanning Trees Algorithm
|
Chris@16
|
7 // Based on academic article of Mint, Read and Tarjan
|
Chris@16
|
8 // Efficient Algorithm for Common Spanning Tree Problem
|
Chris@16
|
9 // Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346-347
|
Chris@16
|
10
|
Chris@16
|
11
|
Chris@16
|
12 #ifndef BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP
|
Chris@16
|
13 #define BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP
|
Chris@16
|
14
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/config.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/bimap.hpp>
|
Chris@16
|
19 #include <boost/type_traits.hpp>
|
Chris@16
|
20 #include <boost/concept/requires.hpp>
|
Chris@16
|
21 #include <boost/graph/graph_traits.hpp>
|
Chris@16
|
22 #include <boost/graph/undirected_dfs.hpp>
|
Chris@16
|
23 #include <boost/graph/connected_components.hpp>
|
Chris@16
|
24 #include <boost/graph/filtered_graph.hpp>
|
Chris@16
|
25 #include <vector>
|
Chris@16
|
26 #include <stack>
|
Chris@16
|
27 #include <map>
|
Chris@16
|
28
|
Chris@16
|
29
|
Chris@16
|
30 namespace boost
|
Chris@16
|
31 {
|
Chris@16
|
32
|
Chris@16
|
33
|
Chris@16
|
34 namespace detail {
|
Chris@16
|
35
|
Chris@16
|
36
|
Chris@16
|
37 template
|
Chris@16
|
38 <
|
Chris@16
|
39 typename TreeMap,
|
Chris@16
|
40 typename PredMap,
|
Chris@16
|
41 typename DistMap,
|
Chris@16
|
42 typename LowMap,
|
Chris@16
|
43 typename Buffer
|
Chris@16
|
44 >
|
Chris@16
|
45 struct bridges_visitor: public default_dfs_visitor
|
Chris@16
|
46 {
|
Chris@16
|
47 bridges_visitor(
|
Chris@16
|
48 TreeMap tree,
|
Chris@16
|
49 PredMap pred,
|
Chris@16
|
50 DistMap dist,
|
Chris@16
|
51 LowMap low,
|
Chris@16
|
52 Buffer& buffer
|
Chris@16
|
53 ): mTree(tree), mPred(pred), mDist(dist), mLow(low), mBuffer(buffer)
|
Chris@16
|
54 { mNum = -1; }
|
Chris@16
|
55
|
Chris@16
|
56 template <typename Vertex, typename Graph>
|
Chris@16
|
57 void initialize_vertex(const Vertex& u, const Graph& g)
|
Chris@16
|
58 {
|
Chris@16
|
59 put(mPred, u, u);
|
Chris@16
|
60 put(mDist, u, -1);
|
Chris@16
|
61 }
|
Chris@16
|
62
|
Chris@16
|
63 template <typename Vertex, typename Graph>
|
Chris@16
|
64 void discover_vertex(const Vertex& u, const Graph& g)
|
Chris@16
|
65 {
|
Chris@16
|
66 put(mDist, u, ++mNum);
|
Chris@16
|
67 put(mLow, u, get(mDist, u));
|
Chris@16
|
68 }
|
Chris@16
|
69
|
Chris@16
|
70 template <typename Edge, typename Graph>
|
Chris@16
|
71 void tree_edge(const Edge& e, const Graph& g)
|
Chris@16
|
72 {
|
Chris@16
|
73 put(mPred, target(e, g), source(e, g));
|
Chris@16
|
74 put(mTree, target(e, g), e);
|
Chris@16
|
75 }
|
Chris@16
|
76
|
Chris@16
|
77 template <typename Edge, typename Graph>
|
Chris@16
|
78 void back_edge(const Edge& e, const Graph& g)
|
Chris@16
|
79 {
|
Chris@16
|
80 put(mLow, source(e, g),
|
Chris@16
|
81 (std::min)(get(mLow, source(e, g)), get(mDist, target(e, g))));
|
Chris@16
|
82 }
|
Chris@16
|
83
|
Chris@16
|
84 template <typename Vertex, typename Graph>
|
Chris@16
|
85 void finish_vertex(const Vertex& u, const Graph& g)
|
Chris@16
|
86 {
|
Chris@16
|
87 Vertex parent = get(mPred, u);
|
Chris@16
|
88 if(get(mLow, u) > get(mDist, parent))
|
Chris@16
|
89 mBuffer.push(get(mTree, u));
|
Chris@16
|
90 put(mLow, parent,
|
Chris@16
|
91 (std::min)(get(mLow, parent), get(mLow, u)));
|
Chris@16
|
92 }
|
Chris@16
|
93
|
Chris@16
|
94 TreeMap mTree;
|
Chris@16
|
95 PredMap mPred;
|
Chris@16
|
96 DistMap mDist;
|
Chris@16
|
97 LowMap mLow;
|
Chris@16
|
98 Buffer& mBuffer;
|
Chris@16
|
99 int mNum;
|
Chris@16
|
100 };
|
Chris@16
|
101
|
Chris@16
|
102
|
Chris@16
|
103 template <typename Buffer>
|
Chris@16
|
104 struct cycle_finder: public base_visitor< cycle_finder<Buffer> >
|
Chris@16
|
105 {
|
Chris@16
|
106 typedef on_back_edge event_filter;
|
Chris@16
|
107 cycle_finder(): mBuffer(0) { }
|
Chris@16
|
108 cycle_finder(Buffer* buffer)
|
Chris@16
|
109 : mBuffer(buffer) { }
|
Chris@16
|
110 template <typename Edge, typename Graph>
|
Chris@16
|
111 void operator()(const Edge& e, const Graph& g)
|
Chris@16
|
112 {
|
Chris@16
|
113 if(mBuffer)
|
Chris@16
|
114 mBuffer->push(e);
|
Chris@16
|
115 }
|
Chris@16
|
116 Buffer* mBuffer;
|
Chris@16
|
117 };
|
Chris@16
|
118
|
Chris@16
|
119
|
Chris@16
|
120 template <typename DeletedMap>
|
Chris@16
|
121 struct deleted_edge_status
|
Chris@16
|
122 {
|
Chris@16
|
123 deleted_edge_status() { }
|
Chris@16
|
124 deleted_edge_status(DeletedMap map): mMap(map) { }
|
Chris@16
|
125 template <typename Edge>
|
Chris@16
|
126 bool operator()(const Edge& e) const
|
Chris@16
|
127 { return (!get(mMap, e)); }
|
Chris@16
|
128 DeletedMap mMap;
|
Chris@16
|
129 };
|
Chris@16
|
130
|
Chris@16
|
131
|
Chris@16
|
132 template <typename InLMap>
|
Chris@16
|
133 struct inL_edge_status
|
Chris@16
|
134 {
|
Chris@16
|
135 inL_edge_status() { }
|
Chris@16
|
136 inL_edge_status(InLMap map): mMap(map) { }
|
Chris@16
|
137 template <typename Edge>
|
Chris@16
|
138 bool operator()(const Edge& e) const
|
Chris@16
|
139 { return get(mMap, e); }
|
Chris@16
|
140 InLMap mMap;
|
Chris@16
|
141 };
|
Chris@16
|
142
|
Chris@16
|
143
|
Chris@16
|
144 template <
|
Chris@16
|
145 typename Graph,
|
Chris@16
|
146 typename Func,
|
Chris@16
|
147 typename Seq,
|
Chris@16
|
148 typename Map
|
Chris@16
|
149 >
|
Chris@16
|
150 void rec_two_graphs_common_spanning_trees
|
Chris@16
|
151 (
|
Chris@16
|
152 const Graph& iG,
|
Chris@16
|
153 bimap<
|
Chris@16
|
154 bimaps::set_of<int>,
|
Chris@16
|
155 bimaps::set_of< typename graph_traits<Graph>::edge_descriptor >
|
Chris@16
|
156 > iG_bimap,
|
Chris@16
|
157 Map aiG_inL,
|
Chris@16
|
158 Map diG,
|
Chris@16
|
159 const Graph& vG,
|
Chris@16
|
160 bimap<
|
Chris@16
|
161 bimaps::set_of<int>,
|
Chris@16
|
162 bimaps::set_of< typename graph_traits<Graph>::edge_descriptor >
|
Chris@16
|
163 > vG_bimap,
|
Chris@16
|
164 Map avG_inL,
|
Chris@16
|
165 Map dvG,
|
Chris@16
|
166 Func func,
|
Chris@16
|
167 Seq inL
|
Chris@16
|
168 )
|
Chris@16
|
169 {
|
Chris@16
|
170 typedef graph_traits<Graph> GraphTraits;
|
Chris@16
|
171
|
Chris@16
|
172 typedef typename GraphTraits::vertex_descriptor vertex_descriptor;
|
Chris@16
|
173 typedef typename GraphTraits::edge_descriptor edge_descriptor;
|
Chris@16
|
174
|
Chris@16
|
175 typedef typename Seq::size_type seq_size_type;
|
Chris@16
|
176
|
Chris@16
|
177 int edges = num_vertices(iG) - 1;
|
Chris@16
|
178 //
|
Chris@16
|
179 // [ Michele Caini ]
|
Chris@16
|
180 //
|
Chris@16
|
181 // Using the condition (edges != 0) leads to the accidental submission of
|
Chris@16
|
182 // sub-graphs ((V-1+1)-fake-tree, named here fat-tree).
|
Chris@16
|
183 // Remove this condition is a workaround for the problem of fat-trees.
|
Chris@16
|
184 // Please do not add that condition, even if it improves performance.
|
Chris@16
|
185 //
|
Chris@16
|
186 // Here is proposed the previous guard (that was wrong):
|
Chris@16
|
187 // for(seq_size_type i = 0; (i < inL.size()) && (edges != 0); ++i)
|
Chris@16
|
188 //
|
Chris@16
|
189 {
|
Chris@16
|
190 for(seq_size_type i = 0; i < inL.size(); ++i)
|
Chris@16
|
191 if(inL[i])
|
Chris@16
|
192 --edges;
|
Chris@16
|
193
|
Chris@16
|
194 if(edges < 0)
|
Chris@16
|
195 return;
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 bool is_tree = (edges == 0);
|
Chris@16
|
199 if(is_tree) {
|
Chris@16
|
200 func(inL);
|
Chris@16
|
201 } else {
|
Chris@16
|
202 std::map<vertex_descriptor, default_color_type> vertex_color;
|
Chris@16
|
203 std::map<edge_descriptor, default_color_type> edge_color;
|
Chris@16
|
204
|
Chris@16
|
205 std::stack<edge_descriptor> iG_buf, vG_buf;
|
Chris@16
|
206 bool found = false;
|
Chris@16
|
207
|
Chris@16
|
208 seq_size_type m;
|
Chris@16
|
209 for(seq_size_type j = 0; j < inL.size() && !found; ++j) {
|
Chris@16
|
210 if(!inL[j]
|
Chris@16
|
211 && !get(diG, iG_bimap.left.at(j))
|
Chris@16
|
212 && !get(dvG, vG_bimap.left.at(j)))
|
Chris@16
|
213 {
|
Chris@16
|
214 put(aiG_inL, iG_bimap.left.at(j), true);
|
Chris@16
|
215 put(avG_inL, vG_bimap.left.at(j), true);
|
Chris@16
|
216
|
Chris@16
|
217 undirected_dfs(
|
Chris@16
|
218 make_filtered_graph(iG,
|
Chris@16
|
219 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
220 std::map<edge_descriptor, bool> > >(aiG_inL)),
|
Chris@16
|
221 make_dfs_visitor(
|
Chris@16
|
222 detail::cycle_finder< std::stack<edge_descriptor> > (&iG_buf)),
|
Chris@16
|
223 associative_property_map<
|
Chris@16
|
224 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
225 associative_property_map<
|
Chris@16
|
226 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
227 );
|
Chris@16
|
228 undirected_dfs(
|
Chris@16
|
229 make_filtered_graph(vG,
|
Chris@16
|
230 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
231 std::map<edge_descriptor, bool> > >(avG_inL)),
|
Chris@16
|
232 make_dfs_visitor(
|
Chris@16
|
233 detail::cycle_finder< std::stack<edge_descriptor> > (&vG_buf)),
|
Chris@16
|
234 associative_property_map<
|
Chris@16
|
235 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
236 associative_property_map<
|
Chris@16
|
237 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
238 );
|
Chris@16
|
239
|
Chris@16
|
240 if(iG_buf.empty() && vG_buf.empty()) {
|
Chris@16
|
241 inL[j] = true;
|
Chris@16
|
242 found = true;
|
Chris@16
|
243 m = j;
|
Chris@16
|
244 } else {
|
Chris@16
|
245 while(!iG_buf.empty()) iG_buf.pop();
|
Chris@16
|
246 while(!vG_buf.empty()) vG_buf.pop();
|
Chris@16
|
247 put(aiG_inL, iG_bimap.left.at(j), false);
|
Chris@16
|
248 put(avG_inL, vG_bimap.left.at(j), false);
|
Chris@16
|
249 }
|
Chris@16
|
250 }
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 if(found) {
|
Chris@16
|
254
|
Chris@16
|
255 std::stack<edge_descriptor> iG_buf_copy, vG_buf_copy;
|
Chris@16
|
256 for(seq_size_type j = 0; j < inL.size(); ++j) {
|
Chris@16
|
257 if(!inL[j]
|
Chris@16
|
258 && !get(diG, iG_bimap.left.at(j))
|
Chris@16
|
259 && !get(dvG, vG_bimap.left.at(j)))
|
Chris@16
|
260 {
|
Chris@16
|
261
|
Chris@16
|
262 put(aiG_inL, iG_bimap.left.at(j), true);
|
Chris@16
|
263 put(avG_inL, vG_bimap.left.at(j), true);
|
Chris@16
|
264
|
Chris@16
|
265 undirected_dfs(
|
Chris@16
|
266 make_filtered_graph(iG,
|
Chris@16
|
267 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
268 std::map<edge_descriptor, bool> > >(aiG_inL)),
|
Chris@16
|
269 make_dfs_visitor(
|
Chris@16
|
270 detail::cycle_finder<
|
Chris@16
|
271 std::stack<edge_descriptor> > (&iG_buf)),
|
Chris@16
|
272 associative_property_map< std::map<
|
Chris@16
|
273 vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
274 associative_property_map<
|
Chris@16
|
275 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
276 );
|
Chris@16
|
277 undirected_dfs(
|
Chris@16
|
278 make_filtered_graph(vG,
|
Chris@16
|
279 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
280 std::map<edge_descriptor, bool> > >(avG_inL)),
|
Chris@16
|
281 make_dfs_visitor(
|
Chris@16
|
282 detail::cycle_finder<
|
Chris@16
|
283 std::stack<edge_descriptor> > (&vG_buf)),
|
Chris@16
|
284 associative_property_map< std::map<
|
Chris@16
|
285 vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
286 associative_property_map<
|
Chris@16
|
287 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
288 );
|
Chris@16
|
289
|
Chris@16
|
290 if(!iG_buf.empty() || !vG_buf.empty()) {
|
Chris@16
|
291 while(!iG_buf.empty()) iG_buf.pop();
|
Chris@16
|
292 while(!vG_buf.empty()) vG_buf.pop();
|
Chris@16
|
293 put(diG, iG_bimap.left.at(j), true);
|
Chris@16
|
294 put(dvG, vG_bimap.left.at(j), true);
|
Chris@16
|
295 iG_buf_copy.push(iG_bimap.left.at(j));
|
Chris@16
|
296 vG_buf_copy.push(vG_bimap.left.at(j));
|
Chris@16
|
297 }
|
Chris@16
|
298
|
Chris@16
|
299 put(aiG_inL, iG_bimap.left.at(j), false);
|
Chris@16
|
300 put(avG_inL, vG_bimap.left.at(j), false);
|
Chris@16
|
301 }
|
Chris@16
|
302 }
|
Chris@16
|
303
|
Chris@16
|
304 // REC
|
Chris@16
|
305 detail::rec_two_graphs_common_spanning_trees<Graph, Func, Seq, Map>
|
Chris@16
|
306 (iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL);
|
Chris@16
|
307
|
Chris@16
|
308 while(!iG_buf_copy.empty()) {
|
Chris@16
|
309 put(diG, iG_buf_copy.top(), false);
|
Chris@16
|
310 put(dvG, vG_bimap.left.at(
|
Chris@16
|
311 iG_bimap.right.at(iG_buf_copy.top())), false);
|
Chris@16
|
312 iG_buf_copy.pop();
|
Chris@16
|
313 }
|
Chris@16
|
314 while(!vG_buf_copy.empty()) {
|
Chris@16
|
315 put(dvG, vG_buf_copy.top(), false);
|
Chris@16
|
316 put(diG, iG_bimap.left.at(
|
Chris@16
|
317 vG_bimap.right.at(vG_buf_copy.top())), false);
|
Chris@16
|
318 vG_buf_copy.pop();
|
Chris@16
|
319 }
|
Chris@16
|
320
|
Chris@16
|
321 inL[m] = false;
|
Chris@16
|
322 put(aiG_inL, iG_bimap.left.at(m), false);
|
Chris@16
|
323 put(avG_inL, vG_bimap.left.at(m), false);
|
Chris@16
|
324
|
Chris@16
|
325 put(diG, iG_bimap.left.at(m), true);
|
Chris@16
|
326 put(dvG, vG_bimap.left.at(m), true);
|
Chris@16
|
327
|
Chris@16
|
328 std::map<vertex_descriptor, edge_descriptor> tree_map;
|
Chris@16
|
329 std::map<vertex_descriptor, vertex_descriptor> pred_map;
|
Chris@16
|
330 std::map<vertex_descriptor, int> dist_map, low_map;
|
Chris@16
|
331
|
Chris@16
|
332 detail::bridges_visitor<
|
Chris@16
|
333 associative_property_map<
|
Chris@16
|
334 std::map<vertex_descriptor, edge_descriptor>
|
Chris@16
|
335 >,
|
Chris@16
|
336 associative_property_map<
|
Chris@16
|
337 std::map<vertex_descriptor, vertex_descriptor>
|
Chris@16
|
338 >,
|
Chris@16
|
339 associative_property_map< std::map<vertex_descriptor, int> >,
|
Chris@16
|
340 associative_property_map< std::map<vertex_descriptor, int> >,
|
Chris@16
|
341 std::stack<edge_descriptor>
|
Chris@16
|
342 >
|
Chris@16
|
343 iG_vis(
|
Chris@16
|
344 associative_property_map<
|
Chris@16
|
345 std::map< vertex_descriptor, edge_descriptor> >(tree_map),
|
Chris@16
|
346 associative_property_map<
|
Chris@16
|
347 std::map< vertex_descriptor, vertex_descriptor> >(pred_map),
|
Chris@16
|
348 associative_property_map<
|
Chris@16
|
349 std::map< vertex_descriptor, int> >(dist_map),
|
Chris@16
|
350 associative_property_map<
|
Chris@16
|
351 std::map< vertex_descriptor, int> >(low_map),
|
Chris@16
|
352 iG_buf
|
Chris@16
|
353 ),
|
Chris@16
|
354 vG_vis(
|
Chris@16
|
355 associative_property_map<
|
Chris@16
|
356 std::map< vertex_descriptor, edge_descriptor> >(tree_map),
|
Chris@16
|
357 associative_property_map<
|
Chris@16
|
358 std::map< vertex_descriptor, vertex_descriptor> >(pred_map),
|
Chris@16
|
359 associative_property_map<
|
Chris@16
|
360 std::map< vertex_descriptor, int> >(dist_map),
|
Chris@16
|
361 associative_property_map<
|
Chris@16
|
362 std::map< vertex_descriptor, int> >(low_map),
|
Chris@16
|
363 vG_buf
|
Chris@16
|
364 );
|
Chris@16
|
365
|
Chris@16
|
366 undirected_dfs(make_filtered_graph(iG,
|
Chris@16
|
367 detail::deleted_edge_status< associative_property_map<
|
Chris@16
|
368 std::map<edge_descriptor, bool> > >(diG)),
|
Chris@16
|
369 iG_vis,
|
Chris@16
|
370 associative_property_map<
|
Chris@16
|
371 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
372 associative_property_map<
|
Chris@16
|
373 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
374 );
|
Chris@16
|
375 undirected_dfs(make_filtered_graph(vG,
|
Chris@16
|
376 detail::deleted_edge_status< associative_property_map<
|
Chris@16
|
377 std::map<edge_descriptor, bool> > >(dvG)),
|
Chris@16
|
378 vG_vis,
|
Chris@16
|
379 associative_property_map<
|
Chris@16
|
380 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
381 associative_property_map<
|
Chris@16
|
382 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
383 );
|
Chris@16
|
384
|
Chris@16
|
385 found = false;
|
Chris@16
|
386 std::stack<edge_descriptor> iG_buf_tmp, vG_buf_tmp;
|
Chris@16
|
387 while(!iG_buf.empty() && !found) {
|
Chris@16
|
388 if(!inL[iG_bimap.right.at(iG_buf.top())]) {
|
Chris@16
|
389 put(aiG_inL, iG_buf.top(), true);
|
Chris@16
|
390 put(avG_inL, vG_bimap.left.at(
|
Chris@16
|
391 iG_bimap.right.at(iG_buf.top())), true);
|
Chris@16
|
392
|
Chris@16
|
393 undirected_dfs(
|
Chris@16
|
394 make_filtered_graph(iG,
|
Chris@16
|
395 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
396 std::map<edge_descriptor, bool> > >(aiG_inL)),
|
Chris@16
|
397 make_dfs_visitor(
|
Chris@16
|
398 detail::cycle_finder<
|
Chris@16
|
399 std::stack<edge_descriptor> > (&iG_buf_tmp)),
|
Chris@16
|
400 associative_property_map<
|
Chris@16
|
401 std::map<
|
Chris@16
|
402 vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
403 associative_property_map<
|
Chris@16
|
404 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
405 );
|
Chris@16
|
406 undirected_dfs(
|
Chris@16
|
407 make_filtered_graph(vG,
|
Chris@16
|
408 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
409 std::map<edge_descriptor, bool> > >(avG_inL)),
|
Chris@16
|
410 make_dfs_visitor(
|
Chris@16
|
411 detail::cycle_finder<
|
Chris@16
|
412 std::stack<edge_descriptor> > (&vG_buf_tmp)),
|
Chris@16
|
413 associative_property_map<
|
Chris@16
|
414 std::map<
|
Chris@16
|
415 vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
416 associative_property_map<
|
Chris@16
|
417 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
418 );
|
Chris@16
|
419
|
Chris@16
|
420 if(!iG_buf_tmp.empty() || !vG_buf_tmp.empty()) {
|
Chris@16
|
421 found = true;
|
Chris@16
|
422 } else {
|
Chris@16
|
423 while(!iG_buf_tmp.empty()) iG_buf_tmp.pop();
|
Chris@16
|
424 while(!vG_buf_tmp.empty()) vG_buf_tmp.pop();
|
Chris@16
|
425 iG_buf_copy.push(iG_buf.top());
|
Chris@16
|
426 }
|
Chris@16
|
427
|
Chris@16
|
428 put(aiG_inL, iG_buf.top(), false);
|
Chris@16
|
429 put(avG_inL, vG_bimap.left.at(
|
Chris@16
|
430 iG_bimap.right.at(iG_buf.top())), false);
|
Chris@16
|
431 }
|
Chris@16
|
432 iG_buf.pop();
|
Chris@16
|
433 }
|
Chris@16
|
434 while(!vG_buf.empty() && !found) {
|
Chris@16
|
435 if(!inL[vG_bimap.right.at(vG_buf.top())]) {
|
Chris@16
|
436 put(avG_inL, vG_buf.top(), true);
|
Chris@16
|
437 put(aiG_inL, iG_bimap.left.at(
|
Chris@16
|
438 vG_bimap.right.at(vG_buf.top())), true);
|
Chris@16
|
439
|
Chris@16
|
440 undirected_dfs(
|
Chris@16
|
441 make_filtered_graph(iG,
|
Chris@16
|
442 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
443 std::map<edge_descriptor, bool> > >(aiG_inL)),
|
Chris@16
|
444 make_dfs_visitor(
|
Chris@16
|
445 detail::cycle_finder<
|
Chris@16
|
446 std::stack<edge_descriptor> > (&iG_buf_tmp)),
|
Chris@16
|
447 associative_property_map<
|
Chris@16
|
448 std::map<
|
Chris@16
|
449 vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
450 associative_property_map<
|
Chris@16
|
451 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
452 );
|
Chris@16
|
453 undirected_dfs(
|
Chris@16
|
454 make_filtered_graph(vG,
|
Chris@16
|
455 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
456 std::map<edge_descriptor, bool> > >(avG_inL)),
|
Chris@16
|
457 make_dfs_visitor(
|
Chris@16
|
458 detail::cycle_finder<
|
Chris@16
|
459 std::stack<edge_descriptor> > (&vG_buf_tmp)),
|
Chris@16
|
460 associative_property_map<
|
Chris@16
|
461 std::map<
|
Chris@16
|
462 vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
463 associative_property_map<
|
Chris@16
|
464 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
465 );
|
Chris@16
|
466
|
Chris@16
|
467 if(!iG_buf_tmp.empty() || !vG_buf_tmp.empty()) {
|
Chris@16
|
468 found = true;
|
Chris@16
|
469 } else {
|
Chris@16
|
470 while(!iG_buf_tmp.empty()) iG_buf_tmp.pop();
|
Chris@16
|
471 while(!vG_buf_tmp.empty()) vG_buf_tmp.pop();
|
Chris@16
|
472 vG_buf_copy.push(vG_buf.top());
|
Chris@16
|
473 }
|
Chris@16
|
474
|
Chris@16
|
475 put(avG_inL, vG_buf.top(), false);
|
Chris@16
|
476 put(aiG_inL, iG_bimap.left.at(
|
Chris@16
|
477 vG_bimap.right.at(vG_buf.top())), false);
|
Chris@16
|
478 }
|
Chris@16
|
479 vG_buf.pop();
|
Chris@16
|
480 }
|
Chris@16
|
481
|
Chris@16
|
482 if(!found) {
|
Chris@16
|
483
|
Chris@16
|
484 while(!iG_buf_copy.empty()) {
|
Chris@16
|
485 inL[iG_bimap.right.at(iG_buf_copy.top())] = true;
|
Chris@16
|
486 put(aiG_inL, iG_buf_copy.top(), true);
|
Chris@16
|
487 put(avG_inL, vG_bimap.left.at(
|
Chris@16
|
488 iG_bimap.right.at(iG_buf_copy.top())), true);
|
Chris@16
|
489 iG_buf.push(iG_buf_copy.top());
|
Chris@16
|
490 iG_buf_copy.pop();
|
Chris@16
|
491 }
|
Chris@16
|
492 while(!vG_buf_copy.empty()) {
|
Chris@16
|
493 inL[vG_bimap.right.at(vG_buf_copy.top())] = true;
|
Chris@16
|
494 put(avG_inL, vG_buf_copy.top(), true);
|
Chris@16
|
495 put(aiG_inL, iG_bimap.left.at(
|
Chris@16
|
496 vG_bimap.right.at(vG_buf_copy.top())), true);
|
Chris@16
|
497 vG_buf.push(vG_buf_copy.top());
|
Chris@16
|
498 vG_buf_copy.pop();
|
Chris@16
|
499 }
|
Chris@16
|
500
|
Chris@16
|
501 // REC
|
Chris@16
|
502 detail::rec_two_graphs_common_spanning_trees<
|
Chris@16
|
503 Graph, Func, Seq, Map>
|
Chris@16
|
504 (iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL);
|
Chris@16
|
505
|
Chris@16
|
506 while(!iG_buf.empty()) {
|
Chris@16
|
507 inL[iG_bimap.right.at(iG_buf.top())] = false;
|
Chris@16
|
508 put(aiG_inL, iG_buf.top(), false);
|
Chris@16
|
509 put(avG_inL, vG_bimap.left.at(
|
Chris@16
|
510 iG_bimap.right.at(iG_buf.top())), false);
|
Chris@16
|
511 iG_buf.pop();
|
Chris@16
|
512 }
|
Chris@16
|
513 while(!vG_buf.empty()) {
|
Chris@16
|
514 inL[vG_bimap.right.at(vG_buf.top())] = false;
|
Chris@16
|
515 put(avG_inL, vG_buf.top(), false);
|
Chris@16
|
516 put(aiG_inL, iG_bimap.left.at(
|
Chris@16
|
517 vG_bimap.right.at(vG_buf.top())), false);
|
Chris@16
|
518 vG_buf.pop();
|
Chris@16
|
519 }
|
Chris@16
|
520
|
Chris@16
|
521 }
|
Chris@16
|
522
|
Chris@16
|
523 put(diG, iG_bimap.left.at(m), false);
|
Chris@16
|
524 put(dvG, vG_bimap.left.at(m), false);
|
Chris@16
|
525
|
Chris@16
|
526 }
|
Chris@16
|
527 }
|
Chris@16
|
528 }
|
Chris@16
|
529
|
Chris@16
|
530 } // namespace detail
|
Chris@16
|
531
|
Chris@16
|
532
|
Chris@16
|
533
|
Chris@16
|
534 template <typename Coll, typename Seq>
|
Chris@16
|
535 struct tree_collector
|
Chris@16
|
536 {
|
Chris@16
|
537
|
Chris@16
|
538 public:
|
Chris@16
|
539 BOOST_CONCEPT_ASSERT((BackInsertionSequence<Coll>));
|
Chris@16
|
540 BOOST_CONCEPT_ASSERT((RandomAccessContainer<Seq>));
|
Chris@16
|
541 BOOST_CONCEPT_ASSERT((CopyConstructible<Seq>));
|
Chris@16
|
542
|
Chris@16
|
543 typedef typename Coll::value_type coll_value_type;
|
Chris@16
|
544 typedef typename Seq::value_type seq_value_type;
|
Chris@16
|
545
|
Chris@16
|
546 BOOST_STATIC_ASSERT((is_same<coll_value_type, Seq>::value));
|
Chris@16
|
547 BOOST_STATIC_ASSERT((is_same<seq_value_type, bool>::value));
|
Chris@16
|
548
|
Chris@16
|
549 tree_collector(Coll& seqs): mSeqs(seqs) { }
|
Chris@16
|
550
|
Chris@16
|
551 inline void operator()(Seq seq)
|
Chris@16
|
552 { mSeqs.push_back(seq); }
|
Chris@16
|
553
|
Chris@16
|
554 private:
|
Chris@16
|
555 Coll& mSeqs;
|
Chris@16
|
556
|
Chris@16
|
557 };
|
Chris@16
|
558
|
Chris@16
|
559
|
Chris@16
|
560
|
Chris@16
|
561 template <
|
Chris@16
|
562 typename Graph,
|
Chris@16
|
563 typename Order,
|
Chris@16
|
564 typename Func,
|
Chris@16
|
565 typename Seq
|
Chris@16
|
566 >
|
Chris@16
|
567 BOOST_CONCEPT_REQUIRES(
|
Chris@16
|
568 ((RandomAccessContainer<Order>))
|
Chris@16
|
569 ((IncidenceGraphConcept<Graph>))
|
Chris@16
|
570 ((UnaryFunction<Func, void, Seq>))
|
Chris@16
|
571 ((Mutable_RandomAccessContainer<Seq>))
|
Chris@16
|
572 ((VertexAndEdgeListGraphConcept<Graph>)),
|
Chris@16
|
573 (void)
|
Chris@16
|
574 )
|
Chris@16
|
575 two_graphs_common_spanning_trees
|
Chris@16
|
576 (
|
Chris@16
|
577 const Graph& iG,
|
Chris@16
|
578 Order iG_map,
|
Chris@16
|
579 const Graph& vG,
|
Chris@16
|
580 Order vG_map,
|
Chris@16
|
581 Func func,
|
Chris@16
|
582 Seq inL
|
Chris@16
|
583 )
|
Chris@16
|
584 {
|
Chris@16
|
585 typedef graph_traits<Graph> GraphTraits;
|
Chris@16
|
586
|
Chris@16
|
587 typedef typename GraphTraits::directed_category directed_category;
|
Chris@16
|
588 typedef typename GraphTraits::vertex_descriptor vertex_descriptor;
|
Chris@16
|
589 typedef typename GraphTraits::edge_descriptor edge_descriptor;
|
Chris@16
|
590
|
Chris@16
|
591 typedef typename GraphTraits::edges_size_type edges_size_type;
|
Chris@16
|
592 typedef typename GraphTraits::edge_iterator edge_iterator;
|
Chris@16
|
593
|
Chris@16
|
594 typedef typename Seq::value_type seq_value_type;
|
Chris@16
|
595 typedef typename Seq::size_type seq_size_type;
|
Chris@16
|
596
|
Chris@16
|
597 typedef typename Order::value_type order_value_type;
|
Chris@16
|
598 typedef typename Order::size_type order_size_type;
|
Chris@16
|
599
|
Chris@16
|
600 BOOST_STATIC_ASSERT((is_same<order_value_type, edge_descriptor>::value));
|
Chris@16
|
601 BOOST_CONCEPT_ASSERT((Convertible<order_size_type, edges_size_type>));
|
Chris@16
|
602
|
Chris@16
|
603 BOOST_CONCEPT_ASSERT((Convertible<seq_size_type, edges_size_type>));
|
Chris@16
|
604 BOOST_STATIC_ASSERT((is_same<seq_value_type, bool>::value));
|
Chris@16
|
605
|
Chris@16
|
606 BOOST_STATIC_ASSERT((is_same<directed_category, undirected_tag>::value));
|
Chris@16
|
607
|
Chris@16
|
608 if(num_vertices(iG) != num_vertices(vG))
|
Chris@16
|
609 return;
|
Chris@16
|
610
|
Chris@16
|
611 if(inL.size() != num_edges(iG)
|
Chris@16
|
612 || inL.size() != num_edges(vG))
|
Chris@16
|
613 return;
|
Chris@16
|
614
|
Chris@16
|
615 if(iG_map.size() != num_edges(iG)
|
Chris@16
|
616 || vG_map.size() != num_edges(vG))
|
Chris@16
|
617 return;
|
Chris@16
|
618
|
Chris@16
|
619 typedef bimaps::bimap<
|
Chris@16
|
620 bimaps::set_of< int >,
|
Chris@16
|
621 bimaps::set_of< order_value_type >
|
Chris@16
|
622 > bimap_type;
|
Chris@16
|
623 typedef typename bimap_type::value_type bimap_value;
|
Chris@16
|
624
|
Chris@16
|
625 bimap_type iG_bimap, vG_bimap;
|
Chris@16
|
626 for(order_size_type i = 0; i < iG_map.size(); ++i)
|
Chris@16
|
627 iG_bimap.insert(bimap_value(i, iG_map[i]));
|
Chris@16
|
628 for(order_size_type i = 0; i < vG_map.size(); ++i)
|
Chris@16
|
629 vG_bimap.insert(bimap_value(i, vG_map[i]));
|
Chris@16
|
630
|
Chris@16
|
631 edge_iterator current, last;
|
Chris@16
|
632 boost::tuples::tie(current, last) = edges(iG);
|
Chris@16
|
633 for(; current != last; ++current)
|
Chris@16
|
634 if(iG_bimap.right.find(*current) == iG_bimap.right.end())
|
Chris@16
|
635 return;
|
Chris@16
|
636 boost::tuples::tie(current, last) = edges(vG);
|
Chris@16
|
637 for(; current != last; ++current)
|
Chris@16
|
638 if(vG_bimap.right.find(*current) == vG_bimap.right.end())
|
Chris@16
|
639 return;
|
Chris@16
|
640
|
Chris@16
|
641 std::stack<edge_descriptor> iG_buf, vG_buf;
|
Chris@16
|
642
|
Chris@16
|
643 std::map<vertex_descriptor, edge_descriptor> tree_map;
|
Chris@16
|
644 std::map<vertex_descriptor, vertex_descriptor> pred_map;
|
Chris@16
|
645 std::map<vertex_descriptor, int> dist_map, low_map;
|
Chris@16
|
646
|
Chris@16
|
647 detail::bridges_visitor<
|
Chris@16
|
648 associative_property_map<
|
Chris@16
|
649 std::map<vertex_descriptor, edge_descriptor>
|
Chris@16
|
650 >,
|
Chris@16
|
651 associative_property_map<
|
Chris@16
|
652 std::map<vertex_descriptor, vertex_descriptor>
|
Chris@16
|
653 >,
|
Chris@16
|
654 associative_property_map< std::map<vertex_descriptor, int> >,
|
Chris@16
|
655 associative_property_map< std::map<vertex_descriptor, int> >,
|
Chris@16
|
656 std::stack<edge_descriptor>
|
Chris@16
|
657 >
|
Chris@16
|
658 iG_vis(
|
Chris@16
|
659 associative_property_map<
|
Chris@16
|
660 std::map< vertex_descriptor, edge_descriptor> >(tree_map),
|
Chris@16
|
661 associative_property_map<
|
Chris@16
|
662 std::map< vertex_descriptor, vertex_descriptor> >(pred_map),
|
Chris@16
|
663 associative_property_map<std::map< vertex_descriptor, int> >(dist_map),
|
Chris@16
|
664 associative_property_map<std::map< vertex_descriptor, int> >(low_map),
|
Chris@16
|
665 iG_buf
|
Chris@16
|
666 ),
|
Chris@16
|
667 vG_vis(
|
Chris@16
|
668 associative_property_map<
|
Chris@16
|
669 std::map< vertex_descriptor, edge_descriptor> >(tree_map),
|
Chris@16
|
670 associative_property_map<
|
Chris@16
|
671 std::map< vertex_descriptor, vertex_descriptor> >(pred_map),
|
Chris@16
|
672 associative_property_map<std::map< vertex_descriptor, int> >(dist_map),
|
Chris@16
|
673 associative_property_map<std::map< vertex_descriptor, int> >(low_map),
|
Chris@16
|
674 vG_buf
|
Chris@16
|
675 );
|
Chris@16
|
676
|
Chris@16
|
677 std::map<vertex_descriptor, default_color_type> vertex_color;
|
Chris@16
|
678 std::map<edge_descriptor, default_color_type> edge_color;
|
Chris@16
|
679
|
Chris@16
|
680 undirected_dfs(iG, iG_vis,
|
Chris@16
|
681 associative_property_map<
|
Chris@16
|
682 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
683 associative_property_map<
|
Chris@16
|
684 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
685 );
|
Chris@16
|
686 undirected_dfs(vG, vG_vis,
|
Chris@16
|
687 associative_property_map<
|
Chris@16
|
688 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
689 associative_property_map<
|
Chris@16
|
690 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
691 );
|
Chris@16
|
692
|
Chris@16
|
693 while(!iG_buf.empty()) {
|
Chris@16
|
694 inL[iG_bimap.right.at(iG_buf.top())] = true;
|
Chris@16
|
695 iG_buf.pop();
|
Chris@16
|
696 }
|
Chris@16
|
697 while(!vG_buf.empty()) {
|
Chris@16
|
698 inL[vG_bimap.right.at(vG_buf.top())] = true;
|
Chris@16
|
699 vG_buf.pop();
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702 std::map<edge_descriptor, bool> iG_inL, vG_inL;
|
Chris@16
|
703 associative_property_map< std::map<edge_descriptor, bool> >
|
Chris@16
|
704 aiG_inL(iG_inL), avG_inL(vG_inL);
|
Chris@16
|
705
|
Chris@16
|
706 for(seq_size_type i = 0; i < inL.size(); ++i)
|
Chris@16
|
707 {
|
Chris@16
|
708 if(inL[i]) {
|
Chris@16
|
709 put(aiG_inL, iG_bimap.left.at(i), true);
|
Chris@16
|
710 put(avG_inL, vG_bimap.left.at(i), true);
|
Chris@16
|
711 } else {
|
Chris@16
|
712 put(aiG_inL, iG_bimap.left.at(i), false);
|
Chris@16
|
713 put(avG_inL, vG_bimap.left.at(i), false);
|
Chris@16
|
714 }
|
Chris@16
|
715 }
|
Chris@16
|
716
|
Chris@16
|
717 undirected_dfs(
|
Chris@16
|
718 make_filtered_graph(iG,
|
Chris@16
|
719 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
720 std::map<edge_descriptor, bool> > >(aiG_inL)),
|
Chris@16
|
721 make_dfs_visitor(
|
Chris@16
|
722 detail::cycle_finder< std::stack<edge_descriptor> > (&iG_buf)),
|
Chris@16
|
723 associative_property_map<
|
Chris@16
|
724 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
725 associative_property_map<
|
Chris@16
|
726 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
727 );
|
Chris@16
|
728 undirected_dfs(
|
Chris@16
|
729 make_filtered_graph(vG,
|
Chris@16
|
730 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
731 std::map<edge_descriptor, bool> > >(avG_inL)),
|
Chris@16
|
732 make_dfs_visitor(
|
Chris@16
|
733 detail::cycle_finder< std::stack<edge_descriptor> > (&vG_buf)),
|
Chris@16
|
734 associative_property_map<
|
Chris@16
|
735 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
736 associative_property_map<
|
Chris@16
|
737 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
738 );
|
Chris@16
|
739
|
Chris@16
|
740 if(iG_buf.empty() && vG_buf.empty()) {
|
Chris@16
|
741
|
Chris@16
|
742 std::map<edge_descriptor, bool> iG_deleted, vG_deleted;
|
Chris@16
|
743 associative_property_map< std::map<edge_descriptor, bool> > diG(iG_deleted);
|
Chris@16
|
744 associative_property_map< std::map<edge_descriptor, bool> > dvG(vG_deleted);
|
Chris@16
|
745
|
Chris@16
|
746 boost::tuples::tie(current, last) = edges(iG);
|
Chris@16
|
747 for(; current != last; ++current)
|
Chris@16
|
748 put(diG, *current, false);
|
Chris@16
|
749 boost::tuples::tie(current, last) = edges(vG);
|
Chris@16
|
750 for(; current != last; ++current)
|
Chris@16
|
751 put(dvG, *current, false);
|
Chris@16
|
752
|
Chris@16
|
753 for(seq_size_type j = 0; j < inL.size(); ++j) {
|
Chris@16
|
754 if(!inL[j]) {
|
Chris@16
|
755 put(aiG_inL, iG_bimap.left.at(j), true);
|
Chris@16
|
756 put(avG_inL, vG_bimap.left.at(j), true);
|
Chris@16
|
757
|
Chris@16
|
758 undirected_dfs(
|
Chris@16
|
759 make_filtered_graph(iG,
|
Chris@16
|
760 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
761 std::map<edge_descriptor, bool> > >(aiG_inL)),
|
Chris@16
|
762 make_dfs_visitor(
|
Chris@16
|
763 detail::cycle_finder< std::stack<edge_descriptor> > (&iG_buf)),
|
Chris@16
|
764 associative_property_map<
|
Chris@16
|
765 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
766 associative_property_map<
|
Chris@16
|
767 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
768 );
|
Chris@16
|
769 undirected_dfs(
|
Chris@16
|
770 make_filtered_graph(vG,
|
Chris@16
|
771 detail::inL_edge_status< associative_property_map<
|
Chris@16
|
772 std::map<edge_descriptor, bool> > >(avG_inL)),
|
Chris@16
|
773 make_dfs_visitor(
|
Chris@16
|
774 detail::cycle_finder< std::stack<edge_descriptor> > (&vG_buf)),
|
Chris@16
|
775 associative_property_map<
|
Chris@16
|
776 std::map<vertex_descriptor, default_color_type> >(vertex_color),
|
Chris@16
|
777 associative_property_map<
|
Chris@16
|
778 std::map<edge_descriptor, default_color_type> >(edge_color)
|
Chris@16
|
779 );
|
Chris@16
|
780
|
Chris@16
|
781 if(!iG_buf.empty() || !vG_buf.empty()) {
|
Chris@16
|
782 while(!iG_buf.empty()) iG_buf.pop();
|
Chris@16
|
783 while(!vG_buf.empty()) vG_buf.pop();
|
Chris@16
|
784 put(diG, iG_bimap.left.at(j), true);
|
Chris@16
|
785 put(dvG, vG_bimap.left.at(j), true);
|
Chris@16
|
786 }
|
Chris@16
|
787
|
Chris@16
|
788 put(aiG_inL, iG_bimap.left.at(j), false);
|
Chris@16
|
789 put(avG_inL, vG_bimap.left.at(j), false);
|
Chris@16
|
790 }
|
Chris@16
|
791 }
|
Chris@16
|
792
|
Chris@16
|
793 int cc = 0;
|
Chris@16
|
794
|
Chris@16
|
795 std::map<vertex_descriptor, int> com_map;
|
Chris@16
|
796 cc += connected_components(
|
Chris@16
|
797 make_filtered_graph(iG,
|
Chris@16
|
798 detail::deleted_edge_status<associative_property_map<
|
Chris@16
|
799 std::map<edge_descriptor, bool> > >(diG)),
|
Chris@16
|
800 associative_property_map<std::map<vertex_descriptor, int> >(com_map)
|
Chris@16
|
801 );
|
Chris@16
|
802 cc += connected_components(
|
Chris@16
|
803 make_filtered_graph(vG,
|
Chris@16
|
804 detail::deleted_edge_status<associative_property_map<
|
Chris@16
|
805 std::map<edge_descriptor, bool> > >(dvG)),
|
Chris@16
|
806 associative_property_map< std::map<vertex_descriptor, int> >(com_map)
|
Chris@16
|
807 );
|
Chris@16
|
808
|
Chris@16
|
809 if(cc != 2)
|
Chris@16
|
810 return;
|
Chris@16
|
811
|
Chris@16
|
812 // REC
|
Chris@16
|
813 detail::rec_two_graphs_common_spanning_trees<Graph, Func, Seq,
|
Chris@16
|
814 associative_property_map< std::map<edge_descriptor, bool> > >
|
Chris@16
|
815 (iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL);
|
Chris@16
|
816
|
Chris@16
|
817 }
|
Chris@16
|
818
|
Chris@16
|
819 }
|
Chris@16
|
820
|
Chris@16
|
821
|
Chris@16
|
822 template <
|
Chris@16
|
823 typename Graph,
|
Chris@16
|
824 typename Func,
|
Chris@16
|
825 typename Seq
|
Chris@16
|
826 >
|
Chris@16
|
827 BOOST_CONCEPT_REQUIRES(
|
Chris@16
|
828 ((IncidenceGraphConcept<Graph>))
|
Chris@16
|
829 ((EdgeListGraphConcept<Graph>)),
|
Chris@16
|
830 (void)
|
Chris@16
|
831 )
|
Chris@16
|
832 two_graphs_common_spanning_trees
|
Chris@16
|
833 (
|
Chris@16
|
834 const Graph& iG,
|
Chris@16
|
835 const Graph& vG,
|
Chris@16
|
836 Func func,
|
Chris@16
|
837 Seq inL
|
Chris@16
|
838 )
|
Chris@16
|
839 {
|
Chris@16
|
840 typedef graph_traits<Graph> GraphTraits;
|
Chris@16
|
841
|
Chris@16
|
842 typedef typename GraphTraits::edge_descriptor edge_descriptor;
|
Chris@16
|
843 typedef typename GraphTraits::edge_iterator edge_iterator;
|
Chris@16
|
844
|
Chris@16
|
845 std::vector<edge_descriptor> iGO, vGO;
|
Chris@16
|
846 edge_iterator curr, last;
|
Chris@16
|
847
|
Chris@16
|
848 boost::tuples::tie(curr, last) = edges(iG);
|
Chris@16
|
849 for(; curr != last; ++curr)
|
Chris@16
|
850 iGO.push_back(*curr);
|
Chris@16
|
851
|
Chris@16
|
852 boost::tuples::tie(curr, last) = edges(vG);
|
Chris@16
|
853 for(; curr != last; ++curr)
|
Chris@16
|
854 vGO.push_back(*curr);
|
Chris@16
|
855
|
Chris@16
|
856 two_graphs_common_spanning_trees(iG, iGO, vG, vGO, func, inL);
|
Chris@16
|
857 }
|
Chris@16
|
858
|
Chris@16
|
859
|
Chris@16
|
860 } // namespace boost
|
Chris@16
|
861
|
Chris@16
|
862
|
Chris@16
|
863 #endif // BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP
|