lemongraph 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +674 -0
  4. data/README.md +6 -0
  5. data/ext/lemon-1.3.1/AUTHORS +26 -0
  6. data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
  7. data/ext/lemon-1.3.1/INSTALL +167 -0
  8. data/ext/lemon-1.3.1/LICENSE +32 -0
  9. data/ext/lemon-1.3.1/NEWS +337 -0
  10. data/ext/lemon-1.3.1/README +50 -0
  11. data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
  12. data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
  13. data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
  14. data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
  15. data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
  16. data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
  17. data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
  18. data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
  19. data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
  20. data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
  21. data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
  22. data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
  23. data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
  24. data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
  25. data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
  26. data/ext/lemon-1.3.1/lemon/assert.h +214 -0
  27. data/ext/lemon-1.3.1/lemon/base.cc +37 -0
  28. data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
  29. data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
  30. data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
  31. data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
  32. data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
  33. data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
  34. data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
  35. data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
  36. data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
  37. data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
  38. data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
  39. data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
  40. data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
  41. data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
  42. data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
  43. data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
  44. data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
  45. data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
  46. data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
  47. data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
  48. data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
  49. data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
  50. data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
  51. data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
  52. data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
  53. data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
  54. data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
  55. data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
  56. data/ext/lemon-1.3.1/lemon/clp.h +164 -0
  57. data/ext/lemon-1.3.1/lemon/color.cc +44 -0
  58. data/ext/lemon-1.3.1/lemon/color.h +204 -0
  59. data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
  60. data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
  61. data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
  62. data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
  63. data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
  64. data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
  65. data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
  66. data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
  67. data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
  68. data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
  69. data/ext/lemon-1.3.1/lemon/core.h +2506 -0
  70. data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
  71. data/ext/lemon-1.3.1/lemon/counter.h +249 -0
  72. data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
  73. data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
  74. data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
  75. data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
  76. data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
  77. data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
  78. data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
  79. data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
  80. data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
  81. data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
  82. data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
  83. data/ext/lemon-1.3.1/lemon/error.h +276 -0
  84. data/ext/lemon-1.3.1/lemon/euler.h +287 -0
  85. data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
  86. data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
  87. data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
  88. data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
  89. data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
  90. data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
  91. data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
  92. data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
  93. data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
  94. data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
  95. data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
  96. data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
  97. data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
  98. data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
  99. data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
  100. data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
  101. data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
  102. data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
  103. data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
  104. data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
  105. data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
  106. data/ext/lemon-1.3.1/lemon/lp.h +95 -0
  107. data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
  108. data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
  109. data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
  110. data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
  111. data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
  112. data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
  113. data/ext/lemon-1.3.1/lemon/math.h +77 -0
  114. data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
  115. data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
  116. data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
  117. data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
  118. data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
  119. data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
  120. data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
  121. data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
  122. data/ext/lemon-1.3.1/lemon/path.h +1164 -0
  123. data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
  124. data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
  125. data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
  126. data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
  127. data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
  128. data/ext/lemon-1.3.1/lemon/random.cc +29 -0
  129. data/ext/lemon-1.3.1/lemon/random.h +1005 -0
  130. data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
  131. data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
  132. data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
  133. data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
  134. data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
  135. data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
  136. data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
  137. data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
  138. data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
  139. data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
  140. data/ext/lemongraph/arc_map.cc +1007 -0
  141. data/ext/lemongraph/digraph.cc +282 -0
  142. data/ext/lemongraph/digraph_arc.cc +153 -0
  143. data/ext/lemongraph/digraph_node.cc +277 -0
  144. data/ext/lemongraph/edge_map.cc +770 -0
  145. data/ext/lemongraph/extconf.rb +53 -0
  146. data/ext/lemongraph/graph.cc +351 -0
  147. data/ext/lemongraph/graph_arc.cc +95 -0
  148. data/ext/lemongraph/graph_edge.cc +153 -0
  149. data/ext/lemongraph/graph_item.cc +76 -0
  150. data/ext/lemongraph/graph_node.cc +321 -0
  151. data/ext/lemongraph/lemongraph.cc +260 -0
  152. data/ext/lemongraph/lemongraph.hh +295 -0
  153. data/ext/lemongraph/lemongraph.map +6 -0
  154. data/ext/lemongraph/lemongraph_export.hh +31 -0
  155. data/ext/lemongraph/node_map.cc +1011 -0
  156. data/lemongraph.gemspec +176 -0
  157. data/lib/lemongraph/graphviz.rb +240 -0
  158. data/lib/lemongraph/version.rb +4 -0
  159. data/lib/lemongraph.rb +21 -0
  160. data/samples/lemondeps.rb +38 -0
  161. metadata +202 -0
@@ -0,0 +1,1688 @@
1
+ /* -*- mode: C++; indent-tabs-mode: nil; -*-
2
+ *
3
+ * This file is a part of LEMON, a generic C++ optimization library.
4
+ *
5
+ * Copyright (C) 2003-2013
6
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
+ *
9
+ * Permission to use, modify and distribute this software is granted
10
+ * provided that this copyright notice appears in all copies. For
11
+ * precise terms see the accompanying LICENSE file.
12
+ *
13
+ * This software is provided "AS IS" with no warranty of any kind,
14
+ * express or implied, and with no claim as to its suitability for any
15
+ * purpose.
16
+ *
17
+ */
18
+
19
+ #ifndef LEMON_CONNECTIVITY_H
20
+ #define LEMON_CONNECTIVITY_H
21
+
22
+ #include <lemon/dfs.h>
23
+ #include <lemon/bfs.h>
24
+ #include <lemon/core.h>
25
+ #include <lemon/maps.h>
26
+ #include <lemon/adaptors.h>
27
+
28
+ #include <lemon/concepts/digraph.h>
29
+ #include <lemon/concepts/graph.h>
30
+ #include <lemon/concept_check.h>
31
+
32
+ #include <stack>
33
+ #include <functional>
34
+
35
+ /// \ingroup graph_properties
36
+ /// \file
37
+ /// \brief Connectivity algorithms
38
+ ///
39
+ /// Connectivity algorithms
40
+
41
+ namespace lemon {
42
+
43
+ /// \ingroup graph_properties
44
+ ///
45
+ /// \brief Check whether an undirected graph is connected.
46
+ ///
47
+ /// This function checks whether the given undirected graph is connected,
48
+ /// i.e. there is a path between any two nodes in the graph.
49
+ ///
50
+ /// \return \c true if the graph is connected.
51
+ /// \note By definition, the empty graph is connected.
52
+ ///
53
+ /// \see countConnectedComponents(), connectedComponents()
54
+ /// \see stronglyConnected()
55
+ template <typename Graph>
56
+ bool connected(const Graph& graph) {
57
+ checkConcept<concepts::Graph, Graph>();
58
+ typedef typename Graph::NodeIt NodeIt;
59
+ if (NodeIt(graph) == INVALID) return true;
60
+ Dfs<Graph> dfs(graph);
61
+ dfs.run(NodeIt(graph));
62
+ for (NodeIt it(graph); it != INVALID; ++it) {
63
+ if (!dfs.reached(it)) {
64
+ return false;
65
+ }
66
+ }
67
+ return true;
68
+ }
69
+
70
+ /// \ingroup graph_properties
71
+ ///
72
+ /// \brief Count the number of connected components of an undirected graph
73
+ ///
74
+ /// This function counts the number of connected components of the given
75
+ /// undirected graph.
76
+ ///
77
+ /// The connected components are the classes of an equivalence relation
78
+ /// on the nodes of an undirected graph. Two nodes are in the same class
79
+ /// if they are connected with a path.
80
+ ///
81
+ /// \return The number of connected components.
82
+ /// \note By definition, the empty graph consists
83
+ /// of zero connected components.
84
+ ///
85
+ /// \see connected(), connectedComponents()
86
+ template <typename Graph>
87
+ int countConnectedComponents(const Graph &graph) {
88
+ checkConcept<concepts::Graph, Graph>();
89
+ typedef typename Graph::Node Node;
90
+ typedef typename Graph::Arc Arc;
91
+
92
+ typedef NullMap<Node, Arc> PredMap;
93
+ typedef NullMap<Node, int> DistMap;
94
+
95
+ int compNum = 0;
96
+ typename Bfs<Graph>::
97
+ template SetPredMap<PredMap>::
98
+ template SetDistMap<DistMap>::
99
+ Create bfs(graph);
100
+
101
+ PredMap predMap;
102
+ bfs.predMap(predMap);
103
+
104
+ DistMap distMap;
105
+ bfs.distMap(distMap);
106
+
107
+ bfs.init();
108
+ for(typename Graph::NodeIt n(graph); n != INVALID; ++n) {
109
+ if (!bfs.reached(n)) {
110
+ bfs.addSource(n);
111
+ bfs.start();
112
+ ++compNum;
113
+ }
114
+ }
115
+ return compNum;
116
+ }
117
+
118
+ /// \ingroup graph_properties
119
+ ///
120
+ /// \brief Find the connected components of an undirected graph
121
+ ///
122
+ /// This function finds the connected components of the given undirected
123
+ /// graph.
124
+ ///
125
+ /// The connected components are the classes of an equivalence relation
126
+ /// on the nodes of an undirected graph. Two nodes are in the same class
127
+ /// if they are connected with a path.
128
+ ///
129
+ /// \image html connected_components.png
130
+ /// \image latex connected_components.eps "Connected components" width=\textwidth
131
+ ///
132
+ /// \param graph The undirected graph.
133
+ /// \retval compMap A writable node map. The values will be set from 0 to
134
+ /// the number of the connected components minus one. Each value of the map
135
+ /// will be set exactly once, and the values of a certain component will be
136
+ /// set continuously.
137
+ /// \return The number of connected components.
138
+ /// \note By definition, the empty graph consists
139
+ /// of zero connected components.
140
+ ///
141
+ /// \see connected(), countConnectedComponents()
142
+ template <class Graph, class NodeMap>
143
+ int connectedComponents(const Graph &graph, NodeMap &compMap) {
144
+ checkConcept<concepts::Graph, Graph>();
145
+ typedef typename Graph::Node Node;
146
+ typedef typename Graph::Arc Arc;
147
+ checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
148
+
149
+ typedef NullMap<Node, Arc> PredMap;
150
+ typedef NullMap<Node, int> DistMap;
151
+
152
+ int compNum = 0;
153
+ typename Bfs<Graph>::
154
+ template SetPredMap<PredMap>::
155
+ template SetDistMap<DistMap>::
156
+ Create bfs(graph);
157
+
158
+ PredMap predMap;
159
+ bfs.predMap(predMap);
160
+
161
+ DistMap distMap;
162
+ bfs.distMap(distMap);
163
+
164
+ bfs.init();
165
+ for(typename Graph::NodeIt n(graph); n != INVALID; ++n) {
166
+ if(!bfs.reached(n)) {
167
+ bfs.addSource(n);
168
+ while (!bfs.emptyQueue()) {
169
+ compMap.set(bfs.nextNode(), compNum);
170
+ bfs.processNextNode();
171
+ }
172
+ ++compNum;
173
+ }
174
+ }
175
+ return compNum;
176
+ }
177
+
178
+ namespace _connectivity_bits {
179
+
180
+ template <typename Digraph, typename Iterator >
181
+ struct LeaveOrderVisitor : public DfsVisitor<Digraph> {
182
+ public:
183
+ typedef typename Digraph::Node Node;
184
+ LeaveOrderVisitor(Iterator it) : _it(it) {}
185
+
186
+ void leave(const Node& node) {
187
+ *(_it++) = node;
188
+ }
189
+
190
+ private:
191
+ Iterator _it;
192
+ };
193
+
194
+ template <typename Digraph, typename Map>
195
+ struct FillMapVisitor : public DfsVisitor<Digraph> {
196
+ public:
197
+ typedef typename Digraph::Node Node;
198
+ typedef typename Map::Value Value;
199
+
200
+ FillMapVisitor(Map& map, Value& value)
201
+ : _map(map), _value(value) {}
202
+
203
+ void reach(const Node& node) {
204
+ _map.set(node, _value);
205
+ }
206
+ private:
207
+ Map& _map;
208
+ Value& _value;
209
+ };
210
+
211
+ template <typename Digraph, typename ArcMap>
212
+ struct StronglyConnectedCutArcsVisitor : public DfsVisitor<Digraph> {
213
+ public:
214
+ typedef typename Digraph::Node Node;
215
+ typedef typename Digraph::Arc Arc;
216
+
217
+ StronglyConnectedCutArcsVisitor(const Digraph& digraph,
218
+ ArcMap& cutMap,
219
+ int& cutNum)
220
+ : _digraph(digraph), _cutMap(cutMap), _cutNum(cutNum),
221
+ _compMap(digraph, -1), _num(-1) {
222
+ }
223
+
224
+ void start(const Node&) {
225
+ ++_num;
226
+ }
227
+
228
+ void reach(const Node& node) {
229
+ _compMap.set(node, _num);
230
+ }
231
+
232
+ void examine(const Arc& arc) {
233
+ if (_compMap[_digraph.source(arc)] !=
234
+ _compMap[_digraph.target(arc)]) {
235
+ _cutMap.set(arc, true);
236
+ ++_cutNum;
237
+ }
238
+ }
239
+ private:
240
+ const Digraph& _digraph;
241
+ ArcMap& _cutMap;
242
+ int& _cutNum;
243
+
244
+ typename Digraph::template NodeMap<int> _compMap;
245
+ int _num;
246
+ };
247
+
248
+ }
249
+
250
+
251
+ /// \ingroup graph_properties
252
+ ///
253
+ /// \brief Check whether a directed graph is strongly connected.
254
+ ///
255
+ /// This function checks whether the given directed graph is strongly
256
+ /// connected, i.e. any two nodes of the digraph are
257
+ /// connected with directed paths in both direction.
258
+ ///
259
+ /// \return \c true if the digraph is strongly connected.
260
+ /// \note By definition, the empty digraph is strongly connected.
261
+ ///
262
+ /// \see countStronglyConnectedComponents(), stronglyConnectedComponents()
263
+ /// \see connected()
264
+ template <typename Digraph>
265
+ bool stronglyConnected(const Digraph& digraph) {
266
+ checkConcept<concepts::Digraph, Digraph>();
267
+
268
+ typedef typename Digraph::Node Node;
269
+ typedef typename Digraph::NodeIt NodeIt;
270
+
271
+ typename Digraph::Node source = NodeIt(digraph);
272
+ if (source == INVALID) return true;
273
+
274
+ using namespace _connectivity_bits;
275
+
276
+ typedef DfsVisitor<Digraph> Visitor;
277
+ Visitor visitor;
278
+
279
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
280
+ dfs.init();
281
+ dfs.addSource(source);
282
+ dfs.start();
283
+
284
+ for (NodeIt it(digraph); it != INVALID; ++it) {
285
+ if (!dfs.reached(it)) {
286
+ return false;
287
+ }
288
+ }
289
+
290
+ typedef ReverseDigraph<const Digraph> RDigraph;
291
+ typedef typename RDigraph::NodeIt RNodeIt;
292
+ RDigraph rdigraph(digraph);
293
+
294
+ typedef DfsVisitor<RDigraph> RVisitor;
295
+ RVisitor rvisitor;
296
+
297
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
298
+ rdfs.init();
299
+ rdfs.addSource(source);
300
+ rdfs.start();
301
+
302
+ for (RNodeIt it(rdigraph); it != INVALID; ++it) {
303
+ if (!rdfs.reached(it)) {
304
+ return false;
305
+ }
306
+ }
307
+
308
+ return true;
309
+ }
310
+
311
+ /// \ingroup graph_properties
312
+ ///
313
+ /// \brief Count the number of strongly connected components of a
314
+ /// directed graph
315
+ ///
316
+ /// This function counts the number of strongly connected components of
317
+ /// the given directed graph.
318
+ ///
319
+ /// The strongly connected components are the classes of an
320
+ /// equivalence relation on the nodes of a digraph. Two nodes are in
321
+ /// the same class if they are connected with directed paths in both
322
+ /// direction.
323
+ ///
324
+ /// \return The number of strongly connected components.
325
+ /// \note By definition, the empty digraph has zero
326
+ /// strongly connected components.
327
+ ///
328
+ /// \see stronglyConnected(), stronglyConnectedComponents()
329
+ template <typename Digraph>
330
+ int countStronglyConnectedComponents(const Digraph& digraph) {
331
+ checkConcept<concepts::Digraph, Digraph>();
332
+
333
+ using namespace _connectivity_bits;
334
+
335
+ typedef typename Digraph::Node Node;
336
+ typedef typename Digraph::Arc Arc;
337
+ typedef typename Digraph::NodeIt NodeIt;
338
+ typedef typename Digraph::ArcIt ArcIt;
339
+
340
+ typedef std::vector<Node> Container;
341
+ typedef typename Container::iterator Iterator;
342
+
343
+ Container nodes(countNodes(digraph));
344
+ typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
345
+ Visitor visitor(nodes.begin());
346
+
347
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
348
+ dfs.init();
349
+ for (NodeIt it(digraph); it != INVALID; ++it) {
350
+ if (!dfs.reached(it)) {
351
+ dfs.addSource(it);
352
+ dfs.start();
353
+ }
354
+ }
355
+
356
+ typedef typename Container::reverse_iterator RIterator;
357
+ typedef ReverseDigraph<const Digraph> RDigraph;
358
+
359
+ RDigraph rdigraph(digraph);
360
+
361
+ typedef DfsVisitor<Digraph> RVisitor;
362
+ RVisitor rvisitor;
363
+
364
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
365
+
366
+ int compNum = 0;
367
+
368
+ rdfs.init();
369
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
370
+ if (!rdfs.reached(*it)) {
371
+ rdfs.addSource(*it);
372
+ rdfs.start();
373
+ ++compNum;
374
+ }
375
+ }
376
+ return compNum;
377
+ }
378
+
379
+ /// \ingroup graph_properties
380
+ ///
381
+ /// \brief Find the strongly connected components of a directed graph
382
+ ///
383
+ /// This function finds the strongly connected components of the given
384
+ /// directed graph. In addition, the numbering of the components will
385
+ /// satisfy that there is no arc going from a higher numbered component
386
+ /// to a lower one (i.e. it provides a topological order of the components).
387
+ ///
388
+ /// The strongly connected components are the classes of an
389
+ /// equivalence relation on the nodes of a digraph. Two nodes are in
390
+ /// the same class if they are connected with directed paths in both
391
+ /// direction.
392
+ ///
393
+ /// \image html strongly_connected_components.png
394
+ /// \image latex strongly_connected_components.eps "Strongly connected components" width=\textwidth
395
+ ///
396
+ /// \param digraph The digraph.
397
+ /// \retval compMap A writable node map. The values will be set from 0 to
398
+ /// the number of the strongly connected components minus one. Each value
399
+ /// of the map will be set exactly once, and the values of a certain
400
+ /// component will be set continuously.
401
+ /// \return The number of strongly connected components.
402
+ /// \note By definition, the empty digraph has zero
403
+ /// strongly connected components.
404
+ ///
405
+ /// \see stronglyConnected(), countStronglyConnectedComponents()
406
+ template <typename Digraph, typename NodeMap>
407
+ int stronglyConnectedComponents(const Digraph& digraph, NodeMap& compMap) {
408
+ checkConcept<concepts::Digraph, Digraph>();
409
+ typedef typename Digraph::Node Node;
410
+ typedef typename Digraph::NodeIt NodeIt;
411
+ checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
412
+
413
+ using namespace _connectivity_bits;
414
+
415
+ typedef std::vector<Node> Container;
416
+ typedef typename Container::iterator Iterator;
417
+
418
+ Container nodes(countNodes(digraph));
419
+ typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
420
+ Visitor visitor(nodes.begin());
421
+
422
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
423
+ dfs.init();
424
+ for (NodeIt it(digraph); it != INVALID; ++it) {
425
+ if (!dfs.reached(it)) {
426
+ dfs.addSource(it);
427
+ dfs.start();
428
+ }
429
+ }
430
+
431
+ typedef typename Container::reverse_iterator RIterator;
432
+ typedef ReverseDigraph<const Digraph> RDigraph;
433
+
434
+ RDigraph rdigraph(digraph);
435
+
436
+ int compNum = 0;
437
+
438
+ typedef FillMapVisitor<RDigraph, NodeMap> RVisitor;
439
+ RVisitor rvisitor(compMap, compNum);
440
+
441
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
442
+
443
+ rdfs.init();
444
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
445
+ if (!rdfs.reached(*it)) {
446
+ rdfs.addSource(*it);
447
+ rdfs.start();
448
+ ++compNum;
449
+ }
450
+ }
451
+ return compNum;
452
+ }
453
+
454
+ /// \ingroup graph_properties
455
+ ///
456
+ /// \brief Find the cut arcs of the strongly connected components.
457
+ ///
458
+ /// This function finds the cut arcs of the strongly connected components
459
+ /// of the given digraph.
460
+ ///
461
+ /// The strongly connected components are the classes of an
462
+ /// equivalence relation on the nodes of a digraph. Two nodes are in
463
+ /// the same class if they are connected with directed paths in both
464
+ /// direction.
465
+ /// The strongly connected components are separated by the cut arcs.
466
+ ///
467
+ /// \param digraph The digraph.
468
+ /// \retval cutMap A writable arc map. The values will be set to \c true
469
+ /// for the cut arcs (exactly once for each cut arc), and will not be
470
+ /// changed for other arcs.
471
+ /// \return The number of cut arcs.
472
+ ///
473
+ /// \see stronglyConnected(), stronglyConnectedComponents()
474
+ template <typename Digraph, typename ArcMap>
475
+ int stronglyConnectedCutArcs(const Digraph& digraph, ArcMap& cutMap) {
476
+ checkConcept<concepts::Digraph, Digraph>();
477
+ typedef typename Digraph::Node Node;
478
+ typedef typename Digraph::Arc Arc;
479
+ typedef typename Digraph::NodeIt NodeIt;
480
+ checkConcept<concepts::WriteMap<Arc, bool>, ArcMap>();
481
+
482
+ using namespace _connectivity_bits;
483
+
484
+ typedef std::vector<Node> Container;
485
+ typedef typename Container::iterator Iterator;
486
+
487
+ Container nodes(countNodes(digraph));
488
+ typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
489
+ Visitor visitor(nodes.begin());
490
+
491
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
492
+ dfs.init();
493
+ for (NodeIt it(digraph); it != INVALID; ++it) {
494
+ if (!dfs.reached(it)) {
495
+ dfs.addSource(it);
496
+ dfs.start();
497
+ }
498
+ }
499
+
500
+ typedef typename Container::reverse_iterator RIterator;
501
+ typedef ReverseDigraph<const Digraph> RDigraph;
502
+
503
+ RDigraph rdigraph(digraph);
504
+
505
+ int cutNum = 0;
506
+
507
+ typedef StronglyConnectedCutArcsVisitor<RDigraph, ArcMap> RVisitor;
508
+ RVisitor rvisitor(rdigraph, cutMap, cutNum);
509
+
510
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
511
+
512
+ rdfs.init();
513
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
514
+ if (!rdfs.reached(*it)) {
515
+ rdfs.addSource(*it);
516
+ rdfs.start();
517
+ }
518
+ }
519
+ return cutNum;
520
+ }
521
+
522
+ namespace _connectivity_bits {
523
+
524
+ template <typename Digraph>
525
+ class CountBiNodeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
526
+ public:
527
+ typedef typename Digraph::Node Node;
528
+ typedef typename Digraph::Arc Arc;
529
+ typedef typename Digraph::Edge Edge;
530
+
531
+ CountBiNodeConnectedComponentsVisitor(const Digraph& graph, int &compNum)
532
+ : _graph(graph), _compNum(compNum),
533
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
534
+
535
+ void start(const Node& node) {
536
+ _predMap.set(node, INVALID);
537
+ }
538
+
539
+ void reach(const Node& node) {
540
+ _numMap.set(node, _num);
541
+ _retMap.set(node, _num);
542
+ ++_num;
543
+ }
544
+
545
+ void discover(const Arc& edge) {
546
+ _predMap.set(_graph.target(edge), _graph.source(edge));
547
+ }
548
+
549
+ void examine(const Arc& edge) {
550
+ if (_graph.source(edge) == _graph.target(edge) &&
551
+ _graph.direction(edge)) {
552
+ ++_compNum;
553
+ return;
554
+ }
555
+ if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
556
+ return;
557
+ }
558
+ if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
559
+ _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
560
+ }
561
+ }
562
+
563
+ void backtrack(const Arc& edge) {
564
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
565
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
566
+ }
567
+ if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
568
+ ++_compNum;
569
+ }
570
+ }
571
+
572
+ private:
573
+ const Digraph& _graph;
574
+ int& _compNum;
575
+
576
+ typename Digraph::template NodeMap<int> _numMap;
577
+ typename Digraph::template NodeMap<int> _retMap;
578
+ typename Digraph::template NodeMap<Node> _predMap;
579
+ int _num;
580
+ };
581
+
582
+ template <typename Digraph, typename ArcMap>
583
+ class BiNodeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
584
+ public:
585
+ typedef typename Digraph::Node Node;
586
+ typedef typename Digraph::Arc Arc;
587
+ typedef typename Digraph::Edge Edge;
588
+
589
+ BiNodeConnectedComponentsVisitor(const Digraph& graph,
590
+ ArcMap& compMap, int &compNum)
591
+ : _graph(graph), _compMap(compMap), _compNum(compNum),
592
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
593
+
594
+ void start(const Node& node) {
595
+ _predMap.set(node, INVALID);
596
+ }
597
+
598
+ void reach(const Node& node) {
599
+ _numMap.set(node, _num);
600
+ _retMap.set(node, _num);
601
+ ++_num;
602
+ }
603
+
604
+ void discover(const Arc& edge) {
605
+ Node target = _graph.target(edge);
606
+ _predMap.set(target, edge);
607
+ _edgeStack.push(edge);
608
+ }
609
+
610
+ void examine(const Arc& edge) {
611
+ Node source = _graph.source(edge);
612
+ Node target = _graph.target(edge);
613
+ if (source == target && _graph.direction(edge)) {
614
+ _compMap.set(edge, _compNum);
615
+ ++_compNum;
616
+ return;
617
+ }
618
+ if (_numMap[target] < _numMap[source]) {
619
+ if (_predMap[source] != _graph.oppositeArc(edge)) {
620
+ _edgeStack.push(edge);
621
+ }
622
+ }
623
+ if (_predMap[source] != INVALID &&
624
+ target == _graph.source(_predMap[source])) {
625
+ return;
626
+ }
627
+ if (_retMap[source] > _numMap[target]) {
628
+ _retMap.set(source, _numMap[target]);
629
+ }
630
+ }
631
+
632
+ void backtrack(const Arc& edge) {
633
+ Node source = _graph.source(edge);
634
+ Node target = _graph.target(edge);
635
+ if (_retMap[source] > _retMap[target]) {
636
+ _retMap.set(source, _retMap[target]);
637
+ }
638
+ if (_numMap[source] <= _retMap[target]) {
639
+ while (_edgeStack.top() != edge) {
640
+ _compMap.set(_edgeStack.top(), _compNum);
641
+ _edgeStack.pop();
642
+ }
643
+ _compMap.set(edge, _compNum);
644
+ _edgeStack.pop();
645
+ ++_compNum;
646
+ }
647
+ }
648
+
649
+ private:
650
+ const Digraph& _graph;
651
+ ArcMap& _compMap;
652
+ int& _compNum;
653
+
654
+ typename Digraph::template NodeMap<int> _numMap;
655
+ typename Digraph::template NodeMap<int> _retMap;
656
+ typename Digraph::template NodeMap<Arc> _predMap;
657
+ std::stack<Edge> _edgeStack;
658
+ int _num;
659
+ };
660
+
661
+
662
+ template <typename Digraph, typename NodeMap>
663
+ class BiNodeConnectedCutNodesVisitor : public DfsVisitor<Digraph> {
664
+ public:
665
+ typedef typename Digraph::Node Node;
666
+ typedef typename Digraph::Arc Arc;
667
+ typedef typename Digraph::Edge Edge;
668
+
669
+ BiNodeConnectedCutNodesVisitor(const Digraph& graph, NodeMap& cutMap,
670
+ int& cutNum)
671
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
672
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
673
+
674
+ void start(const Node& node) {
675
+ _predMap.set(node, INVALID);
676
+ rootCut = false;
677
+ }
678
+
679
+ void reach(const Node& node) {
680
+ _numMap.set(node, _num);
681
+ _retMap.set(node, _num);
682
+ ++_num;
683
+ }
684
+
685
+ void discover(const Arc& edge) {
686
+ _predMap.set(_graph.target(edge), _graph.source(edge));
687
+ }
688
+
689
+ void examine(const Arc& edge) {
690
+ if (_graph.source(edge) == _graph.target(edge) &&
691
+ _graph.direction(edge)) {
692
+ if (!_cutMap[_graph.source(edge)]) {
693
+ _cutMap.set(_graph.source(edge), true);
694
+ ++_cutNum;
695
+ }
696
+ return;
697
+ }
698
+ if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
699
+ if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
700
+ _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
701
+ }
702
+ }
703
+
704
+ void backtrack(const Arc& edge) {
705
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
706
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
707
+ }
708
+ if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
709
+ if (_predMap[_graph.source(edge)] != INVALID) {
710
+ if (!_cutMap[_graph.source(edge)]) {
711
+ _cutMap.set(_graph.source(edge), true);
712
+ ++_cutNum;
713
+ }
714
+ } else if (rootCut) {
715
+ if (!_cutMap[_graph.source(edge)]) {
716
+ _cutMap.set(_graph.source(edge), true);
717
+ ++_cutNum;
718
+ }
719
+ } else {
720
+ rootCut = true;
721
+ }
722
+ }
723
+ }
724
+
725
+ private:
726
+ const Digraph& _graph;
727
+ NodeMap& _cutMap;
728
+ int& _cutNum;
729
+
730
+ typename Digraph::template NodeMap<int> _numMap;
731
+ typename Digraph::template NodeMap<int> _retMap;
732
+ typename Digraph::template NodeMap<Node> _predMap;
733
+ std::stack<Edge> _edgeStack;
734
+ int _num;
735
+ bool rootCut;
736
+ };
737
+
738
+ }
739
+
740
+ template <typename Graph>
741
+ int countBiNodeConnectedComponents(const Graph& graph);
742
+
743
+ /// \ingroup graph_properties
744
+ ///
745
+ /// \brief Check whether an undirected graph is bi-node-connected.
746
+ ///
747
+ /// This function checks whether the given undirected graph is
748
+ /// bi-node-connected, i.e. a connected graph without articulation
749
+ /// node.
750
+ ///
751
+ /// \return \c true if the graph bi-node-connected.
752
+ ///
753
+ /// \note By definition,
754
+ /// \li a graph consisting of zero or one node is bi-node-connected,
755
+ /// \li a graph consisting of two isolated nodes
756
+ /// is \e not bi-node-connected and
757
+ /// \li a graph consisting of two nodes connected by an edge
758
+ /// is bi-node-connected.
759
+ ///
760
+ /// \see countBiNodeConnectedComponents(), biNodeConnectedComponents()
761
+ template <typename Graph>
762
+ bool biNodeConnected(const Graph& graph) {
763
+ bool hasNonIsolated = false, hasIsolated = false;
764
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
765
+ if (typename Graph::OutArcIt(graph, n) == INVALID) {
766
+ if (hasIsolated || hasNonIsolated) {
767
+ return false;
768
+ } else {
769
+ hasIsolated = true;
770
+ }
771
+ } else {
772
+ if (hasIsolated) {
773
+ return false;
774
+ } else {
775
+ hasNonIsolated = true;
776
+ }
777
+ }
778
+ }
779
+ return countBiNodeConnectedComponents(graph) <= 1;
780
+ }
781
+
782
+ /// \ingroup graph_properties
783
+ ///
784
+ /// \brief Count the number of bi-node-connected components of an
785
+ /// undirected graph.
786
+ ///
787
+ /// This function counts the number of bi-node-connected components of
788
+ /// the given undirected graph.
789
+ ///
790
+ /// The bi-node-connected components are the classes of an equivalence
791
+ /// relation on the edges of a undirected graph. Two edges are in the
792
+ /// same class if they are on same circle.
793
+ ///
794
+ /// \return The number of bi-node-connected components.
795
+ ///
796
+ /// \see biNodeConnected(), biNodeConnectedComponents()
797
+ template <typename Graph>
798
+ int countBiNodeConnectedComponents(const Graph& graph) {
799
+ checkConcept<concepts::Graph, Graph>();
800
+ typedef typename Graph::NodeIt NodeIt;
801
+
802
+ using namespace _connectivity_bits;
803
+
804
+ typedef CountBiNodeConnectedComponentsVisitor<Graph> Visitor;
805
+
806
+ int compNum = 0;
807
+ Visitor visitor(graph, compNum);
808
+
809
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
810
+ dfs.init();
811
+
812
+ for (NodeIt it(graph); it != INVALID; ++it) {
813
+ if (!dfs.reached(it)) {
814
+ dfs.addSource(it);
815
+ dfs.start();
816
+ }
817
+ }
818
+ return compNum;
819
+ }
820
+
821
+ /// \ingroup graph_properties
822
+ ///
823
+ /// \brief Find the bi-node-connected components of an undirected graph.
824
+ ///
825
+ /// This function finds the bi-node-connected components of the given
826
+ /// undirected graph.
827
+ ///
828
+ /// The bi-node-connected components are the classes of an equivalence
829
+ /// relation on the edges of a undirected graph. Two edges are in the
830
+ /// same class if they are on same circle.
831
+ ///
832
+ /// \image html node_biconnected_components.png
833
+ /// \image latex node_biconnected_components.eps "bi-node-connected components" width=\textwidth
834
+ ///
835
+ /// \param graph The undirected graph.
836
+ /// \retval compMap A writable edge map. The values will be set from 0
837
+ /// to the number of the bi-node-connected components minus one. Each
838
+ /// value of the map will be set exactly once, and the values of a
839
+ /// certain component will be set continuously.
840
+ /// \return The number of bi-node-connected components.
841
+ ///
842
+ /// \see biNodeConnected(), countBiNodeConnectedComponents()
843
+ template <typename Graph, typename EdgeMap>
844
+ int biNodeConnectedComponents(const Graph& graph,
845
+ EdgeMap& compMap) {
846
+ checkConcept<concepts::Graph, Graph>();
847
+ typedef typename Graph::NodeIt NodeIt;
848
+ typedef typename Graph::Edge Edge;
849
+ checkConcept<concepts::WriteMap<Edge, int>, EdgeMap>();
850
+
851
+ using namespace _connectivity_bits;
852
+
853
+ typedef BiNodeConnectedComponentsVisitor<Graph, EdgeMap> Visitor;
854
+
855
+ int compNum = 0;
856
+ Visitor visitor(graph, compMap, compNum);
857
+
858
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
859
+ dfs.init();
860
+
861
+ for (NodeIt it(graph); it != INVALID; ++it) {
862
+ if (!dfs.reached(it)) {
863
+ dfs.addSource(it);
864
+ dfs.start();
865
+ }
866
+ }
867
+ return compNum;
868
+ }
869
+
870
+ /// \ingroup graph_properties
871
+ ///
872
+ /// \brief Find the bi-node-connected cut nodes in an undirected graph.
873
+ ///
874
+ /// This function finds the bi-node-connected cut nodes in the given
875
+ /// undirected graph.
876
+ ///
877
+ /// The bi-node-connected components are the classes of an equivalence
878
+ /// relation on the edges of a undirected graph. Two edges are in the
879
+ /// same class if they are on same circle.
880
+ /// The bi-node-connected components are separted by the cut nodes of
881
+ /// the components.
882
+ ///
883
+ /// \param graph The undirected graph.
884
+ /// \retval cutMap A writable node map. The values will be set to
885
+ /// \c true for the nodes that separate two or more components
886
+ /// (exactly once for each cut node), and will not be changed for
887
+ /// other nodes.
888
+ /// \return The number of the cut nodes.
889
+ ///
890
+ /// \see biNodeConnected(), biNodeConnectedComponents()
891
+ template <typename Graph, typename NodeMap>
892
+ int biNodeConnectedCutNodes(const Graph& graph, NodeMap& cutMap) {
893
+ checkConcept<concepts::Graph, Graph>();
894
+ typedef typename Graph::Node Node;
895
+ typedef typename Graph::NodeIt NodeIt;
896
+ checkConcept<concepts::WriteMap<Node, bool>, NodeMap>();
897
+
898
+ using namespace _connectivity_bits;
899
+
900
+ typedef BiNodeConnectedCutNodesVisitor<Graph, NodeMap> Visitor;
901
+
902
+ int cutNum = 0;
903
+ Visitor visitor(graph, cutMap, cutNum);
904
+
905
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
906
+ dfs.init();
907
+
908
+ for (NodeIt it(graph); it != INVALID; ++it) {
909
+ if (!dfs.reached(it)) {
910
+ dfs.addSource(it);
911
+ dfs.start();
912
+ }
913
+ }
914
+ return cutNum;
915
+ }
916
+
917
+ namespace _connectivity_bits {
918
+
919
+ template <typename Digraph>
920
+ class CountBiEdgeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
921
+ public:
922
+ typedef typename Digraph::Node Node;
923
+ typedef typename Digraph::Arc Arc;
924
+ typedef typename Digraph::Edge Edge;
925
+
926
+ CountBiEdgeConnectedComponentsVisitor(const Digraph& graph, int &compNum)
927
+ : _graph(graph), _compNum(compNum),
928
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
929
+
930
+ void start(const Node& node) {
931
+ _predMap.set(node, INVALID);
932
+ }
933
+
934
+ void reach(const Node& node) {
935
+ _numMap.set(node, _num);
936
+ _retMap.set(node, _num);
937
+ ++_num;
938
+ }
939
+
940
+ void leave(const Node& node) {
941
+ if (_numMap[node] <= _retMap[node]) {
942
+ ++_compNum;
943
+ }
944
+ }
945
+
946
+ void discover(const Arc& edge) {
947
+ _predMap.set(_graph.target(edge), edge);
948
+ }
949
+
950
+ void examine(const Arc& edge) {
951
+ if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
952
+ return;
953
+ }
954
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
955
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
956
+ }
957
+ }
958
+
959
+ void backtrack(const Arc& edge) {
960
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
961
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
962
+ }
963
+ }
964
+
965
+ private:
966
+ const Digraph& _graph;
967
+ int& _compNum;
968
+
969
+ typename Digraph::template NodeMap<int> _numMap;
970
+ typename Digraph::template NodeMap<int> _retMap;
971
+ typename Digraph::template NodeMap<Arc> _predMap;
972
+ int _num;
973
+ };
974
+
975
+ template <typename Digraph, typename NodeMap>
976
+ class BiEdgeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
977
+ public:
978
+ typedef typename Digraph::Node Node;
979
+ typedef typename Digraph::Arc Arc;
980
+ typedef typename Digraph::Edge Edge;
981
+
982
+ BiEdgeConnectedComponentsVisitor(const Digraph& graph,
983
+ NodeMap& compMap, int &compNum)
984
+ : _graph(graph), _compMap(compMap), _compNum(compNum),
985
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
986
+
987
+ void start(const Node& node) {
988
+ _predMap.set(node, INVALID);
989
+ }
990
+
991
+ void reach(const Node& node) {
992
+ _numMap.set(node, _num);
993
+ _retMap.set(node, _num);
994
+ _nodeStack.push(node);
995
+ ++_num;
996
+ }
997
+
998
+ void leave(const Node& node) {
999
+ if (_numMap[node] <= _retMap[node]) {
1000
+ while (_nodeStack.top() != node) {
1001
+ _compMap.set(_nodeStack.top(), _compNum);
1002
+ _nodeStack.pop();
1003
+ }
1004
+ _compMap.set(node, _compNum);
1005
+ _nodeStack.pop();
1006
+ ++_compNum;
1007
+ }
1008
+ }
1009
+
1010
+ void discover(const Arc& edge) {
1011
+ _predMap.set(_graph.target(edge), edge);
1012
+ }
1013
+
1014
+ void examine(const Arc& edge) {
1015
+ if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
1016
+ return;
1017
+ }
1018
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1019
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1020
+ }
1021
+ }
1022
+
1023
+ void backtrack(const Arc& edge) {
1024
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1025
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1026
+ }
1027
+ }
1028
+
1029
+ private:
1030
+ const Digraph& _graph;
1031
+ NodeMap& _compMap;
1032
+ int& _compNum;
1033
+
1034
+ typename Digraph::template NodeMap<int> _numMap;
1035
+ typename Digraph::template NodeMap<int> _retMap;
1036
+ typename Digraph::template NodeMap<Arc> _predMap;
1037
+ std::stack<Node> _nodeStack;
1038
+ int _num;
1039
+ };
1040
+
1041
+
1042
+ template <typename Digraph, typename ArcMap>
1043
+ class BiEdgeConnectedCutEdgesVisitor : public DfsVisitor<Digraph> {
1044
+ public:
1045
+ typedef typename Digraph::Node Node;
1046
+ typedef typename Digraph::Arc Arc;
1047
+ typedef typename Digraph::Edge Edge;
1048
+
1049
+ BiEdgeConnectedCutEdgesVisitor(const Digraph& graph,
1050
+ ArcMap& cutMap, int &cutNum)
1051
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
1052
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
1053
+
1054
+ void start(const Node& node) {
1055
+ _predMap[node] = INVALID;
1056
+ }
1057
+
1058
+ void reach(const Node& node) {
1059
+ _numMap.set(node, _num);
1060
+ _retMap.set(node, _num);
1061
+ ++_num;
1062
+ }
1063
+
1064
+ void leave(const Node& node) {
1065
+ if (_numMap[node] <= _retMap[node]) {
1066
+ if (_predMap[node] != INVALID) {
1067
+ _cutMap.set(_predMap[node], true);
1068
+ ++_cutNum;
1069
+ }
1070
+ }
1071
+ }
1072
+
1073
+ void discover(const Arc& edge) {
1074
+ _predMap.set(_graph.target(edge), edge);
1075
+ }
1076
+
1077
+ void examine(const Arc& edge) {
1078
+ if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
1079
+ return;
1080
+ }
1081
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1082
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1083
+ }
1084
+ }
1085
+
1086
+ void backtrack(const Arc& edge) {
1087
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1088
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1089
+ }
1090
+ }
1091
+
1092
+ private:
1093
+ const Digraph& _graph;
1094
+ ArcMap& _cutMap;
1095
+ int& _cutNum;
1096
+
1097
+ typename Digraph::template NodeMap<int> _numMap;
1098
+ typename Digraph::template NodeMap<int> _retMap;
1099
+ typename Digraph::template NodeMap<Arc> _predMap;
1100
+ int _num;
1101
+ };
1102
+ }
1103
+
1104
+ template <typename Graph>
1105
+ int countBiEdgeConnectedComponents(const Graph& graph);
1106
+
1107
+ /// \ingroup graph_properties
1108
+ ///
1109
+ /// \brief Check whether an undirected graph is bi-edge-connected.
1110
+ ///
1111
+ /// This function checks whether the given undirected graph is
1112
+ /// bi-edge-connected, i.e. any two nodes are connected with at least
1113
+ /// two edge-disjoint paths.
1114
+ ///
1115
+ /// \return \c true if the graph is bi-edge-connected.
1116
+ /// \note By definition, the empty graph is bi-edge-connected.
1117
+ ///
1118
+ /// \see countBiEdgeConnectedComponents(), biEdgeConnectedComponents()
1119
+ template <typename Graph>
1120
+ bool biEdgeConnected(const Graph& graph) {
1121
+ return countBiEdgeConnectedComponents(graph) <= 1;
1122
+ }
1123
+
1124
+ /// \ingroup graph_properties
1125
+ ///
1126
+ /// \brief Count the number of bi-edge-connected components of an
1127
+ /// undirected graph.
1128
+ ///
1129
+ /// This function counts the number of bi-edge-connected components of
1130
+ /// the given undirected graph.
1131
+ ///
1132
+ /// The bi-edge-connected components are the classes of an equivalence
1133
+ /// relation on the nodes of an undirected graph. Two nodes are in the
1134
+ /// same class if they are connected with at least two edge-disjoint
1135
+ /// paths.
1136
+ ///
1137
+ /// \return The number of bi-edge-connected components.
1138
+ ///
1139
+ /// \see biEdgeConnected(), biEdgeConnectedComponents()
1140
+ template <typename Graph>
1141
+ int countBiEdgeConnectedComponents(const Graph& graph) {
1142
+ checkConcept<concepts::Graph, Graph>();
1143
+ typedef typename Graph::NodeIt NodeIt;
1144
+
1145
+ using namespace _connectivity_bits;
1146
+
1147
+ typedef CountBiEdgeConnectedComponentsVisitor<Graph> Visitor;
1148
+
1149
+ int compNum = 0;
1150
+ Visitor visitor(graph, compNum);
1151
+
1152
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
1153
+ dfs.init();
1154
+
1155
+ for (NodeIt it(graph); it != INVALID; ++it) {
1156
+ if (!dfs.reached(it)) {
1157
+ dfs.addSource(it);
1158
+ dfs.start();
1159
+ }
1160
+ }
1161
+ return compNum;
1162
+ }
1163
+
1164
+ /// \ingroup graph_properties
1165
+ ///
1166
+ /// \brief Find the bi-edge-connected components of an undirected graph.
1167
+ ///
1168
+ /// This function finds the bi-edge-connected components of the given
1169
+ /// undirected graph.
1170
+ ///
1171
+ /// The bi-edge-connected components are the classes of an equivalence
1172
+ /// relation on the nodes of an undirected graph. Two nodes are in the
1173
+ /// same class if they are connected with at least two edge-disjoint
1174
+ /// paths.
1175
+ ///
1176
+ /// \image html edge_biconnected_components.png
1177
+ /// \image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth
1178
+ ///
1179
+ /// \param graph The undirected graph.
1180
+ /// \retval compMap A writable node map. The values will be set from 0 to
1181
+ /// the number of the bi-edge-connected components minus one. Each value
1182
+ /// of the map will be set exactly once, and the values of a certain
1183
+ /// component will be set continuously.
1184
+ /// \return The number of bi-edge-connected components.
1185
+ ///
1186
+ /// \see biEdgeConnected(), countBiEdgeConnectedComponents()
1187
+ template <typename Graph, typename NodeMap>
1188
+ int biEdgeConnectedComponents(const Graph& graph, NodeMap& compMap) {
1189
+ checkConcept<concepts::Graph, Graph>();
1190
+ typedef typename Graph::NodeIt NodeIt;
1191
+ typedef typename Graph::Node Node;
1192
+ checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
1193
+
1194
+ using namespace _connectivity_bits;
1195
+
1196
+ typedef BiEdgeConnectedComponentsVisitor<Graph, NodeMap> Visitor;
1197
+
1198
+ int compNum = 0;
1199
+ Visitor visitor(graph, compMap, compNum);
1200
+
1201
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
1202
+ dfs.init();
1203
+
1204
+ for (NodeIt it(graph); it != INVALID; ++it) {
1205
+ if (!dfs.reached(it)) {
1206
+ dfs.addSource(it);
1207
+ dfs.start();
1208
+ }
1209
+ }
1210
+ return compNum;
1211
+ }
1212
+
1213
+ /// \ingroup graph_properties
1214
+ ///
1215
+ /// \brief Find the bi-edge-connected cut edges in an undirected graph.
1216
+ ///
1217
+ /// This function finds the bi-edge-connected cut edges in the given
1218
+ /// undirected graph.
1219
+ ///
1220
+ /// The bi-edge-connected components are the classes of an equivalence
1221
+ /// relation on the nodes of an undirected graph. Two nodes are in the
1222
+ /// same class if they are connected with at least two edge-disjoint
1223
+ /// paths.
1224
+ /// The bi-edge-connected components are separted by the cut edges of
1225
+ /// the components.
1226
+ ///
1227
+ /// \param graph The undirected graph.
1228
+ /// \retval cutMap A writable edge map. The values will be set to \c true
1229
+ /// for the cut edges (exactly once for each cut edge), and will not be
1230
+ /// changed for other edges.
1231
+ /// \return The number of cut edges.
1232
+ ///
1233
+ /// \see biEdgeConnected(), biEdgeConnectedComponents()
1234
+ template <typename Graph, typename EdgeMap>
1235
+ int biEdgeConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
1236
+ checkConcept<concepts::Graph, Graph>();
1237
+ typedef typename Graph::NodeIt NodeIt;
1238
+ typedef typename Graph::Edge Edge;
1239
+ checkConcept<concepts::WriteMap<Edge, bool>, EdgeMap>();
1240
+
1241
+ using namespace _connectivity_bits;
1242
+
1243
+ typedef BiEdgeConnectedCutEdgesVisitor<Graph, EdgeMap> Visitor;
1244
+
1245
+ int cutNum = 0;
1246
+ Visitor visitor(graph, cutMap, cutNum);
1247
+
1248
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
1249
+ dfs.init();
1250
+
1251
+ for (NodeIt it(graph); it != INVALID; ++it) {
1252
+ if (!dfs.reached(it)) {
1253
+ dfs.addSource(it);
1254
+ dfs.start();
1255
+ }
1256
+ }
1257
+ return cutNum;
1258
+ }
1259
+
1260
+
1261
+ namespace _connectivity_bits {
1262
+
1263
+ template <typename Digraph, typename IntNodeMap>
1264
+ class TopologicalSortVisitor : public DfsVisitor<Digraph> {
1265
+ public:
1266
+ typedef typename Digraph::Node Node;
1267
+ typedef typename Digraph::Arc edge;
1268
+
1269
+ TopologicalSortVisitor(IntNodeMap& order, int num)
1270
+ : _order(order), _num(num) {}
1271
+
1272
+ void leave(const Node& node) {
1273
+ _order.set(node, --_num);
1274
+ }
1275
+
1276
+ private:
1277
+ IntNodeMap& _order;
1278
+ int _num;
1279
+ };
1280
+
1281
+ }
1282
+
1283
+ /// \ingroup graph_properties
1284
+ ///
1285
+ /// \brief Check whether a digraph is DAG.
1286
+ ///
1287
+ /// This function checks whether the given digraph is DAG, i.e.
1288
+ /// \e Directed \e Acyclic \e Graph.
1289
+ /// \return \c true if there is no directed cycle in the digraph.
1290
+ /// \see acyclic()
1291
+ template <typename Digraph>
1292
+ bool dag(const Digraph& digraph) {
1293
+
1294
+ checkConcept<concepts::Digraph, Digraph>();
1295
+
1296
+ typedef typename Digraph::Node Node;
1297
+ typedef typename Digraph::NodeIt NodeIt;
1298
+ typedef typename Digraph::Arc Arc;
1299
+
1300
+ typedef typename Digraph::template NodeMap<bool> ProcessedMap;
1301
+
1302
+ typename Dfs<Digraph>::template SetProcessedMap<ProcessedMap>::
1303
+ Create dfs(digraph);
1304
+
1305
+ ProcessedMap processed(digraph);
1306
+ dfs.processedMap(processed);
1307
+
1308
+ dfs.init();
1309
+ for (NodeIt it(digraph); it != INVALID; ++it) {
1310
+ if (!dfs.reached(it)) {
1311
+ dfs.addSource(it);
1312
+ while (!dfs.emptyQueue()) {
1313
+ Arc arc = dfs.nextArc();
1314
+ Node target = digraph.target(arc);
1315
+ if (dfs.reached(target) && !processed[target]) {
1316
+ return false;
1317
+ }
1318
+ dfs.processNextArc();
1319
+ }
1320
+ }
1321
+ }
1322
+ return true;
1323
+ }
1324
+
1325
+ /// \ingroup graph_properties
1326
+ ///
1327
+ /// \brief Sort the nodes of a DAG into topolgical order.
1328
+ ///
1329
+ /// This function sorts the nodes of the given acyclic digraph (DAG)
1330
+ /// into topolgical order.
1331
+ ///
1332
+ /// \param digraph The digraph, which must be DAG.
1333
+ /// \retval order A writable node map. The values will be set from 0 to
1334
+ /// the number of the nodes in the digraph minus one. Each value of the
1335
+ /// map will be set exactly once, and the values will be set descending
1336
+ /// order.
1337
+ ///
1338
+ /// \see dag(), checkedTopologicalSort()
1339
+ template <typename Digraph, typename NodeMap>
1340
+ void topologicalSort(const Digraph& digraph, NodeMap& order) {
1341
+ using namespace _connectivity_bits;
1342
+
1343
+ checkConcept<concepts::Digraph, Digraph>();
1344
+ checkConcept<concepts::WriteMap<typename Digraph::Node, int>, NodeMap>();
1345
+
1346
+ typedef typename Digraph::Node Node;
1347
+ typedef typename Digraph::NodeIt NodeIt;
1348
+ typedef typename Digraph::Arc Arc;
1349
+
1350
+ TopologicalSortVisitor<Digraph, NodeMap>
1351
+ visitor(order, countNodes(digraph));
1352
+
1353
+ DfsVisit<Digraph, TopologicalSortVisitor<Digraph, NodeMap> >
1354
+ dfs(digraph, visitor);
1355
+
1356
+ dfs.init();
1357
+ for (NodeIt it(digraph); it != INVALID; ++it) {
1358
+ if (!dfs.reached(it)) {
1359
+ dfs.addSource(it);
1360
+ dfs.start();
1361
+ }
1362
+ }
1363
+ }
1364
+
1365
+ /// \ingroup graph_properties
1366
+ ///
1367
+ /// \brief Sort the nodes of a DAG into topolgical order.
1368
+ ///
1369
+ /// This function sorts the nodes of the given acyclic digraph (DAG)
1370
+ /// into topolgical order and also checks whether the given digraph
1371
+ /// is DAG.
1372
+ ///
1373
+ /// \param digraph The digraph.
1374
+ /// \retval order A readable and writable node map. The values will be
1375
+ /// set from 0 to the number of the nodes in the digraph minus one.
1376
+ /// Each value of the map will be set exactly once, and the values will
1377
+ /// be set descending order.
1378
+ /// \return \c false if the digraph is not DAG.
1379
+ ///
1380
+ /// \see dag(), topologicalSort()
1381
+ template <typename Digraph, typename NodeMap>
1382
+ bool checkedTopologicalSort(const Digraph& digraph, NodeMap& order) {
1383
+ using namespace _connectivity_bits;
1384
+
1385
+ checkConcept<concepts::Digraph, Digraph>();
1386
+ checkConcept<concepts::ReadWriteMap<typename Digraph::Node, int>,
1387
+ NodeMap>();
1388
+
1389
+ typedef typename Digraph::Node Node;
1390
+ typedef typename Digraph::NodeIt NodeIt;
1391
+ typedef typename Digraph::Arc Arc;
1392
+
1393
+ for (NodeIt it(digraph); it != INVALID; ++it) {
1394
+ order.set(it, -1);
1395
+ }
1396
+
1397
+ TopologicalSortVisitor<Digraph, NodeMap>
1398
+ visitor(order, countNodes(digraph));
1399
+
1400
+ DfsVisit<Digraph, TopologicalSortVisitor<Digraph, NodeMap> >
1401
+ dfs(digraph, visitor);
1402
+
1403
+ dfs.init();
1404
+ for (NodeIt it(digraph); it != INVALID; ++it) {
1405
+ if (!dfs.reached(it)) {
1406
+ dfs.addSource(it);
1407
+ while (!dfs.emptyQueue()) {
1408
+ Arc arc = dfs.nextArc();
1409
+ Node target = digraph.target(arc);
1410
+ if (dfs.reached(target) && order[target] == -1) {
1411
+ return false;
1412
+ }
1413
+ dfs.processNextArc();
1414
+ }
1415
+ }
1416
+ }
1417
+ return true;
1418
+ }
1419
+
1420
+ /// \ingroup graph_properties
1421
+ ///
1422
+ /// \brief Check whether an undirected graph is acyclic.
1423
+ ///
1424
+ /// This function checks whether the given undirected graph is acyclic.
1425
+ /// \return \c true if there is no cycle in the graph.
1426
+ /// \see dag()
1427
+ template <typename Graph>
1428
+ bool acyclic(const Graph& graph) {
1429
+ checkConcept<concepts::Graph, Graph>();
1430
+ typedef typename Graph::Node Node;
1431
+ typedef typename Graph::NodeIt NodeIt;
1432
+ typedef typename Graph::Arc Arc;
1433
+ Dfs<Graph> dfs(graph);
1434
+ dfs.init();
1435
+ for (NodeIt it(graph); it != INVALID; ++it) {
1436
+ if (!dfs.reached(it)) {
1437
+ dfs.addSource(it);
1438
+ while (!dfs.emptyQueue()) {
1439
+ Arc arc = dfs.nextArc();
1440
+ Node source = graph.source(arc);
1441
+ Node target = graph.target(arc);
1442
+ if (dfs.reached(target) &&
1443
+ dfs.predArc(source) != graph.oppositeArc(arc)) {
1444
+ return false;
1445
+ }
1446
+ dfs.processNextArc();
1447
+ }
1448
+ }
1449
+ }
1450
+ return true;
1451
+ }
1452
+
1453
+ /// \ingroup graph_properties
1454
+ ///
1455
+ /// \brief Check whether an undirected graph is tree.
1456
+ ///
1457
+ /// This function checks whether the given undirected graph is tree.
1458
+ /// \return \c true if the graph is acyclic and connected.
1459
+ /// \see acyclic(), connected()
1460
+ template <typename Graph>
1461
+ bool tree(const Graph& graph) {
1462
+ checkConcept<concepts::Graph, Graph>();
1463
+ typedef typename Graph::Node Node;
1464
+ typedef typename Graph::NodeIt NodeIt;
1465
+ typedef typename Graph::Arc Arc;
1466
+ if (NodeIt(graph) == INVALID) return true;
1467
+ Dfs<Graph> dfs(graph);
1468
+ dfs.init();
1469
+ dfs.addSource(NodeIt(graph));
1470
+ while (!dfs.emptyQueue()) {
1471
+ Arc arc = dfs.nextArc();
1472
+ Node source = graph.source(arc);
1473
+ Node target = graph.target(arc);
1474
+ if (dfs.reached(target) &&
1475
+ dfs.predArc(source) != graph.oppositeArc(arc)) {
1476
+ return false;
1477
+ }
1478
+ dfs.processNextArc();
1479
+ }
1480
+ for (NodeIt it(graph); it != INVALID; ++it) {
1481
+ if (!dfs.reached(it)) {
1482
+ return false;
1483
+ }
1484
+ }
1485
+ return true;
1486
+ }
1487
+
1488
+ namespace _connectivity_bits {
1489
+
1490
+ template <typename Digraph>
1491
+ class BipartiteVisitor : public BfsVisitor<Digraph> {
1492
+ public:
1493
+ typedef typename Digraph::Arc Arc;
1494
+ typedef typename Digraph::Node Node;
1495
+
1496
+ BipartiteVisitor(const Digraph& graph, bool& bipartite)
1497
+ : _graph(graph), _part(graph), _bipartite(bipartite) {}
1498
+
1499
+ void start(const Node& node) {
1500
+ _part[node] = true;
1501
+ }
1502
+ void discover(const Arc& edge) {
1503
+ _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
1504
+ }
1505
+ void examine(const Arc& edge) {
1506
+ _bipartite = _bipartite &&
1507
+ _part[_graph.target(edge)] != _part[_graph.source(edge)];
1508
+ }
1509
+
1510
+ private:
1511
+
1512
+ const Digraph& _graph;
1513
+ typename Digraph::template NodeMap<bool> _part;
1514
+ bool& _bipartite;
1515
+ };
1516
+
1517
+ template <typename Digraph, typename PartMap>
1518
+ class BipartitePartitionsVisitor : public BfsVisitor<Digraph> {
1519
+ public:
1520
+ typedef typename Digraph::Arc Arc;
1521
+ typedef typename Digraph::Node Node;
1522
+
1523
+ BipartitePartitionsVisitor(const Digraph& graph,
1524
+ PartMap& part, bool& bipartite)
1525
+ : _graph(graph), _part(part), _bipartite(bipartite) {}
1526
+
1527
+ void start(const Node& node) {
1528
+ _part.set(node, true);
1529
+ }
1530
+ void discover(const Arc& edge) {
1531
+ _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
1532
+ }
1533
+ void examine(const Arc& edge) {
1534
+ _bipartite = _bipartite &&
1535
+ _part[_graph.target(edge)] != _part[_graph.source(edge)];
1536
+ }
1537
+
1538
+ private:
1539
+
1540
+ const Digraph& _graph;
1541
+ PartMap& _part;
1542
+ bool& _bipartite;
1543
+ };
1544
+ }
1545
+
1546
+ /// \ingroup graph_properties
1547
+ ///
1548
+ /// \brief Check whether an undirected graph is bipartite.
1549
+ ///
1550
+ /// The function checks whether the given undirected graph is bipartite.
1551
+ /// \return \c true if the graph is bipartite.
1552
+ ///
1553
+ /// \see bipartitePartitions()
1554
+ template<typename Graph>
1555
+ bool bipartite(const Graph &graph){
1556
+ using namespace _connectivity_bits;
1557
+
1558
+ checkConcept<concepts::Graph, Graph>();
1559
+
1560
+ typedef typename Graph::NodeIt NodeIt;
1561
+ typedef typename Graph::ArcIt ArcIt;
1562
+
1563
+ bool bipartite = true;
1564
+
1565
+ BipartiteVisitor<Graph>
1566
+ visitor(graph, bipartite);
1567
+ BfsVisit<Graph, BipartiteVisitor<Graph> >
1568
+ bfs(graph, visitor);
1569
+ bfs.init();
1570
+ for(NodeIt it(graph); it != INVALID; ++it) {
1571
+ if(!bfs.reached(it)){
1572
+ bfs.addSource(it);
1573
+ while (!bfs.emptyQueue()) {
1574
+ bfs.processNextNode();
1575
+ if (!bipartite) return false;
1576
+ }
1577
+ }
1578
+ }
1579
+ return true;
1580
+ }
1581
+
1582
+ /// \ingroup graph_properties
1583
+ ///
1584
+ /// \brief Find the bipartite partitions of an undirected graph.
1585
+ ///
1586
+ /// This function checks whether the given undirected graph is bipartite
1587
+ /// and gives back the bipartite partitions.
1588
+ ///
1589
+ /// \image html bipartite_partitions.png
1590
+ /// \image latex bipartite_partitions.eps "Bipartite partititions" width=\textwidth
1591
+ ///
1592
+ /// \param graph The undirected graph.
1593
+ /// \retval partMap A writable node map of \c bool (or convertible) value
1594
+ /// type. The values will be set to \c true for one component and
1595
+ /// \c false for the other one.
1596
+ /// \return \c true if the graph is bipartite, \c false otherwise.
1597
+ ///
1598
+ /// \see bipartite()
1599
+ template<typename Graph, typename NodeMap>
1600
+ bool bipartitePartitions(const Graph &graph, NodeMap &partMap){
1601
+ using namespace _connectivity_bits;
1602
+
1603
+ checkConcept<concepts::Graph, Graph>();
1604
+ checkConcept<concepts::WriteMap<typename Graph::Node, bool>, NodeMap>();
1605
+
1606
+ typedef typename Graph::Node Node;
1607
+ typedef typename Graph::NodeIt NodeIt;
1608
+ typedef typename Graph::ArcIt ArcIt;
1609
+
1610
+ bool bipartite = true;
1611
+
1612
+ BipartitePartitionsVisitor<Graph, NodeMap>
1613
+ visitor(graph, partMap, bipartite);
1614
+ BfsVisit<Graph, BipartitePartitionsVisitor<Graph, NodeMap> >
1615
+ bfs(graph, visitor);
1616
+ bfs.init();
1617
+ for(NodeIt it(graph); it != INVALID; ++it) {
1618
+ if(!bfs.reached(it)){
1619
+ bfs.addSource(it);
1620
+ while (!bfs.emptyQueue()) {
1621
+ bfs.processNextNode();
1622
+ if (!bipartite) return false;
1623
+ }
1624
+ }
1625
+ }
1626
+ return true;
1627
+ }
1628
+
1629
+ /// \ingroup graph_properties
1630
+ ///
1631
+ /// \brief Check whether the given graph contains no loop arcs/edges.
1632
+ ///
1633
+ /// This function returns \c true if there are no loop arcs/edges in
1634
+ /// the given graph. It works for both directed and undirected graphs.
1635
+ template <typename Graph>
1636
+ bool loopFree(const Graph& graph) {
1637
+ for (typename Graph::ArcIt it(graph); it != INVALID; ++it) {
1638
+ if (graph.source(it) == graph.target(it)) return false;
1639
+ }
1640
+ return true;
1641
+ }
1642
+
1643
+ /// \ingroup graph_properties
1644
+ ///
1645
+ /// \brief Check whether the given graph contains no parallel arcs/edges.
1646
+ ///
1647
+ /// This function returns \c true if there are no parallel arcs/edges in
1648
+ /// the given graph. It works for both directed and undirected graphs.
1649
+ template <typename Graph>
1650
+ bool parallelFree(const Graph& graph) {
1651
+ typename Graph::template NodeMap<int> reached(graph, 0);
1652
+ int cnt = 1;
1653
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
1654
+ for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) {
1655
+ if (reached[graph.target(a)] == cnt) return false;
1656
+ reached[graph.target(a)] = cnt;
1657
+ }
1658
+ ++cnt;
1659
+ }
1660
+ return true;
1661
+ }
1662
+
1663
+ /// \ingroup graph_properties
1664
+ ///
1665
+ /// \brief Check whether the given graph is simple.
1666
+ ///
1667
+ /// This function returns \c true if the given graph is simple, i.e.
1668
+ /// it contains no loop arcs/edges and no parallel arcs/edges.
1669
+ /// The function works for both directed and undirected graphs.
1670
+ /// \see loopFree(), parallelFree()
1671
+ template <typename Graph>
1672
+ bool simpleGraph(const Graph& graph) {
1673
+ typename Graph::template NodeMap<int> reached(graph, 0);
1674
+ int cnt = 1;
1675
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
1676
+ reached[n] = cnt;
1677
+ for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) {
1678
+ if (reached[graph.target(a)] == cnt) return false;
1679
+ reached[graph.target(a)] = cnt;
1680
+ }
1681
+ ++cnt;
1682
+ }
1683
+ return true;
1684
+ }
1685
+
1686
+ } //namespace lemon
1687
+
1688
+ #endif //LEMON_CONNECTIVITY_H