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,1015 @@
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_HAO_ORLIN_H
20
+ #define LEMON_HAO_ORLIN_H
21
+
22
+ #include <vector>
23
+ #include <list>
24
+ #include <limits>
25
+
26
+ #include <lemon/maps.h>
27
+ #include <lemon/core.h>
28
+ #include <lemon/tolerance.h>
29
+
30
+ /// \file
31
+ /// \ingroup min_cut
32
+ /// \brief Implementation of the Hao-Orlin algorithm.
33
+ ///
34
+ /// Implementation of the Hao-Orlin algorithm for finding a minimum cut
35
+ /// in a digraph.
36
+
37
+ namespace lemon {
38
+
39
+ /// \ingroup min_cut
40
+ ///
41
+ /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph.
42
+ ///
43
+ /// This class implements the Hao-Orlin algorithm for finding a minimum
44
+ /// value cut in a directed graph \f$D=(V,A)\f$.
45
+ /// It takes a fixed node \f$ source \in V \f$ and
46
+ /// consists of two phases: in the first phase it determines a
47
+ /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
48
+ /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal outgoing
49
+ /// capacity) and in the second phase it determines a minimum cut
50
+ /// with \f$ source \f$ on the sink-side (i.e. a set
51
+ /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal outgoing
52
+ /// capacity). Obviously, the smaller of these two cuts will be a
53
+ /// minimum cut of \f$ D \f$. The algorithm is a modified
54
+ /// preflow push-relabel algorithm. Our implementation calculates
55
+ /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
56
+ /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. A notable
57
+ /// use of this algorithm is testing network reliability.
58
+ ///
59
+ /// For an undirected graph you can run just the first phase of the
60
+ /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
61
+ /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$
62
+ /// time. It is implemented in the NagamochiIbaraki algorithm class.
63
+ ///
64
+ /// \tparam GR The type of the digraph the algorithm runs on.
65
+ /// \tparam CAP The type of the arc map containing the capacities,
66
+ /// which can be any numreric type. The default map type is
67
+ /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
68
+ /// \tparam TOL Tolerance class for handling inexact computations. The
69
+ /// default tolerance type is \ref Tolerance "Tolerance<CAP::Value>".
70
+ #ifdef DOXYGEN
71
+ template <typename GR, typename CAP, typename TOL>
72
+ #else
73
+ template <typename GR,
74
+ typename CAP = typename GR::template ArcMap<int>,
75
+ typename TOL = Tolerance<typename CAP::Value> >
76
+ #endif
77
+ class HaoOrlin {
78
+ public:
79
+
80
+ /// The digraph type of the algorithm
81
+ typedef GR Digraph;
82
+ /// The capacity map type of the algorithm
83
+ typedef CAP CapacityMap;
84
+ /// The tolerance type of the algorithm
85
+ typedef TOL Tolerance;
86
+
87
+ private:
88
+
89
+ typedef typename CapacityMap::Value Value;
90
+
91
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
92
+
93
+ const Digraph& _graph;
94
+ const CapacityMap* _capacity;
95
+
96
+ typedef typename Digraph::template ArcMap<Value> FlowMap;
97
+ FlowMap* _flow;
98
+
99
+ Node _source;
100
+
101
+ int _node_num;
102
+
103
+ // Bucketing structure
104
+ std::vector<Node> _first, _last;
105
+ typename Digraph::template NodeMap<Node>* _next;
106
+ typename Digraph::template NodeMap<Node>* _prev;
107
+ typename Digraph::template NodeMap<bool>* _active;
108
+ typename Digraph::template NodeMap<int>* _bucket;
109
+
110
+ std::vector<bool> _dormant;
111
+
112
+ std::list<std::list<int> > _sets;
113
+ std::list<int>::iterator _highest;
114
+
115
+ typedef typename Digraph::template NodeMap<Value> ExcessMap;
116
+ ExcessMap* _excess;
117
+
118
+ typedef typename Digraph::template NodeMap<bool> SourceSetMap;
119
+ SourceSetMap* _source_set;
120
+
121
+ Value _min_cut;
122
+
123
+ typedef typename Digraph::template NodeMap<bool> MinCutMap;
124
+ MinCutMap* _min_cut_map;
125
+
126
+ Tolerance _tolerance;
127
+
128
+ public:
129
+
130
+ /// \brief Constructor
131
+ ///
132
+ /// Constructor of the algorithm class.
133
+ HaoOrlin(const Digraph& graph, const CapacityMap& capacity,
134
+ const Tolerance& tolerance = Tolerance()) :
135
+ _graph(graph), _capacity(&capacity), _flow(0), _source(),
136
+ _node_num(), _first(), _last(), _next(0), _prev(0),
137
+ _active(0), _bucket(0), _dormant(), _sets(), _highest(),
138
+ _excess(0), _source_set(0), _min_cut(), _min_cut_map(0),
139
+ _tolerance(tolerance) {}
140
+
141
+ ~HaoOrlin() {
142
+ if (_min_cut_map) {
143
+ delete _min_cut_map;
144
+ }
145
+ if (_source_set) {
146
+ delete _source_set;
147
+ }
148
+ if (_excess) {
149
+ delete _excess;
150
+ }
151
+ if (_next) {
152
+ delete _next;
153
+ }
154
+ if (_prev) {
155
+ delete _prev;
156
+ }
157
+ if (_active) {
158
+ delete _active;
159
+ }
160
+ if (_bucket) {
161
+ delete _bucket;
162
+ }
163
+ if (_flow) {
164
+ delete _flow;
165
+ }
166
+ }
167
+
168
+ /// \brief Set the tolerance used by the algorithm.
169
+ ///
170
+ /// This function sets the tolerance object used by the algorithm.
171
+ /// \return <tt>(*this)</tt>
172
+ HaoOrlin& tolerance(const Tolerance& tolerance) {
173
+ _tolerance = tolerance;
174
+ return *this;
175
+ }
176
+
177
+ /// \brief Returns a const reference to the tolerance.
178
+ ///
179
+ /// This function returns a const reference to the tolerance object
180
+ /// used by the algorithm.
181
+ const Tolerance& tolerance() const {
182
+ return _tolerance;
183
+ }
184
+
185
+ private:
186
+
187
+ void activate(const Node& i) {
188
+ (*_active)[i] = true;
189
+
190
+ int bucket = (*_bucket)[i];
191
+
192
+ if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return;
193
+ //unlace
194
+ (*_next)[(*_prev)[i]] = (*_next)[i];
195
+ if ((*_next)[i] != INVALID) {
196
+ (*_prev)[(*_next)[i]] = (*_prev)[i];
197
+ } else {
198
+ _last[bucket] = (*_prev)[i];
199
+ }
200
+ //lace
201
+ (*_next)[i] = _first[bucket];
202
+ (*_prev)[_first[bucket]] = i;
203
+ (*_prev)[i] = INVALID;
204
+ _first[bucket] = i;
205
+ }
206
+
207
+ void deactivate(const Node& i) {
208
+ (*_active)[i] = false;
209
+ int bucket = (*_bucket)[i];
210
+
211
+ if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return;
212
+
213
+ //unlace
214
+ (*_prev)[(*_next)[i]] = (*_prev)[i];
215
+ if ((*_prev)[i] != INVALID) {
216
+ (*_next)[(*_prev)[i]] = (*_next)[i];
217
+ } else {
218
+ _first[bucket] = (*_next)[i];
219
+ }
220
+ //lace
221
+ (*_prev)[i] = _last[bucket];
222
+ (*_next)[_last[bucket]] = i;
223
+ (*_next)[i] = INVALID;
224
+ _last[bucket] = i;
225
+ }
226
+
227
+ void addItem(const Node& i, int bucket) {
228
+ (*_bucket)[i] = bucket;
229
+ if (_last[bucket] != INVALID) {
230
+ (*_prev)[i] = _last[bucket];
231
+ (*_next)[_last[bucket]] = i;
232
+ (*_next)[i] = INVALID;
233
+ _last[bucket] = i;
234
+ } else {
235
+ (*_prev)[i] = INVALID;
236
+ _first[bucket] = i;
237
+ (*_next)[i] = INVALID;
238
+ _last[bucket] = i;
239
+ }
240
+ }
241
+
242
+ void findMinCutOut() {
243
+
244
+ for (NodeIt n(_graph); n != INVALID; ++n) {
245
+ (*_excess)[n] = 0;
246
+ (*_source_set)[n] = false;
247
+ }
248
+
249
+ for (ArcIt a(_graph); a != INVALID; ++a) {
250
+ (*_flow)[a] = 0;
251
+ }
252
+
253
+ int bucket_num = 0;
254
+ std::vector<Node> queue(_node_num);
255
+ int qfirst = 0, qlast = 0, qsep = 0;
256
+
257
+ {
258
+ typename Digraph::template NodeMap<bool> reached(_graph, false);
259
+
260
+ reached[_source] = true;
261
+ bool first_set = true;
262
+
263
+ for (NodeIt t(_graph); t != INVALID; ++t) {
264
+ if (reached[t]) continue;
265
+ _sets.push_front(std::list<int>());
266
+
267
+ queue[qlast++] = t;
268
+ reached[t] = true;
269
+
270
+ while (qfirst != qlast) {
271
+ if (qsep == qfirst) {
272
+ ++bucket_num;
273
+ _sets.front().push_front(bucket_num);
274
+ _dormant[bucket_num] = !first_set;
275
+ _first[bucket_num] = _last[bucket_num] = INVALID;
276
+ qsep = qlast;
277
+ }
278
+
279
+ Node n = queue[qfirst++];
280
+ addItem(n, bucket_num);
281
+
282
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
283
+ Node u = _graph.source(a);
284
+ if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
285
+ reached[u] = true;
286
+ queue[qlast++] = u;
287
+ }
288
+ }
289
+ }
290
+ first_set = false;
291
+ }
292
+
293
+ ++bucket_num;
294
+ (*_bucket)[_source] = 0;
295
+ _dormant[0] = true;
296
+ }
297
+ (*_source_set)[_source] = true;
298
+
299
+ Node target = _last[_sets.back().back()];
300
+ {
301
+ for (OutArcIt a(_graph, _source); a != INVALID; ++a) {
302
+ if (_tolerance.positive((*_capacity)[a])) {
303
+ Node u = _graph.target(a);
304
+ (*_flow)[a] = (*_capacity)[a];
305
+ (*_excess)[u] += (*_capacity)[a];
306
+ if (!(*_active)[u] && u != _source) {
307
+ activate(u);
308
+ }
309
+ }
310
+ }
311
+
312
+ if ((*_active)[target]) {
313
+ deactivate(target);
314
+ }
315
+
316
+ _highest = _sets.back().begin();
317
+ while (_highest != _sets.back().end() &&
318
+ !(*_active)[_first[*_highest]]) {
319
+ ++_highest;
320
+ }
321
+ }
322
+
323
+ while (true) {
324
+ while (_highest != _sets.back().end()) {
325
+ Node n = _first[*_highest];
326
+ Value excess = (*_excess)[n];
327
+ int next_bucket = _node_num;
328
+
329
+ int under_bucket;
330
+ if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
331
+ under_bucket = -1;
332
+ } else {
333
+ under_bucket = *(++std::list<int>::iterator(_highest));
334
+ }
335
+
336
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
337
+ Node v = _graph.target(a);
338
+ if (_dormant[(*_bucket)[v]]) continue;
339
+ Value rem = (*_capacity)[a] - (*_flow)[a];
340
+ if (!_tolerance.positive(rem)) continue;
341
+ if ((*_bucket)[v] == under_bucket) {
342
+ if (!(*_active)[v] && v != target) {
343
+ activate(v);
344
+ }
345
+ if (!_tolerance.less(rem, excess)) {
346
+ (*_flow)[a] += excess;
347
+ (*_excess)[v] += excess;
348
+ excess = 0;
349
+ goto no_more_push;
350
+ } else {
351
+ excess -= rem;
352
+ (*_excess)[v] += rem;
353
+ (*_flow)[a] = (*_capacity)[a];
354
+ }
355
+ } else if (next_bucket > (*_bucket)[v]) {
356
+ next_bucket = (*_bucket)[v];
357
+ }
358
+ }
359
+
360
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
361
+ Node v = _graph.source(a);
362
+ if (_dormant[(*_bucket)[v]]) continue;
363
+ Value rem = (*_flow)[a];
364
+ if (!_tolerance.positive(rem)) continue;
365
+ if ((*_bucket)[v] == under_bucket) {
366
+ if (!(*_active)[v] && v != target) {
367
+ activate(v);
368
+ }
369
+ if (!_tolerance.less(rem, excess)) {
370
+ (*_flow)[a] -= excess;
371
+ (*_excess)[v] += excess;
372
+ excess = 0;
373
+ goto no_more_push;
374
+ } else {
375
+ excess -= rem;
376
+ (*_excess)[v] += rem;
377
+ (*_flow)[a] = 0;
378
+ }
379
+ } else if (next_bucket > (*_bucket)[v]) {
380
+ next_bucket = (*_bucket)[v];
381
+ }
382
+ }
383
+
384
+ no_more_push:
385
+
386
+ (*_excess)[n] = excess;
387
+
388
+ if (excess != 0) {
389
+ if ((*_next)[n] == INVALID) {
390
+ typename std::list<std::list<int> >::iterator new_set =
391
+ _sets.insert(--_sets.end(), std::list<int>());
392
+ new_set->splice(new_set->end(), _sets.back(),
393
+ _sets.back().begin(), ++_highest);
394
+ for (std::list<int>::iterator it = new_set->begin();
395
+ it != new_set->end(); ++it) {
396
+ _dormant[*it] = true;
397
+ }
398
+ while (_highest != _sets.back().end() &&
399
+ !(*_active)[_first[*_highest]]) {
400
+ ++_highest;
401
+ }
402
+ } else if (next_bucket == _node_num) {
403
+ _first[(*_bucket)[n]] = (*_next)[n];
404
+ (*_prev)[(*_next)[n]] = INVALID;
405
+
406
+ std::list<std::list<int> >::iterator new_set =
407
+ _sets.insert(--_sets.end(), std::list<int>());
408
+
409
+ new_set->push_front(bucket_num);
410
+ (*_bucket)[n] = bucket_num;
411
+ _first[bucket_num] = _last[bucket_num] = n;
412
+ (*_next)[n] = INVALID;
413
+ (*_prev)[n] = INVALID;
414
+ _dormant[bucket_num] = true;
415
+ ++bucket_num;
416
+
417
+ while (_highest != _sets.back().end() &&
418
+ !(*_active)[_first[*_highest]]) {
419
+ ++_highest;
420
+ }
421
+ } else {
422
+ _first[*_highest] = (*_next)[n];
423
+ (*_prev)[(*_next)[n]] = INVALID;
424
+
425
+ while (next_bucket != *_highest) {
426
+ --_highest;
427
+ }
428
+
429
+ if (_highest == _sets.back().begin()) {
430
+ _sets.back().push_front(bucket_num);
431
+ _dormant[bucket_num] = false;
432
+ _first[bucket_num] = _last[bucket_num] = INVALID;
433
+ ++bucket_num;
434
+ }
435
+ --_highest;
436
+
437
+ (*_bucket)[n] = *_highest;
438
+ (*_next)[n] = _first[*_highest];
439
+ if (_first[*_highest] != INVALID) {
440
+ (*_prev)[_first[*_highest]] = n;
441
+ } else {
442
+ _last[*_highest] = n;
443
+ }
444
+ _first[*_highest] = n;
445
+ }
446
+ } else {
447
+
448
+ deactivate(n);
449
+ if (!(*_active)[_first[*_highest]]) {
450
+ ++_highest;
451
+ if (_highest != _sets.back().end() &&
452
+ !(*_active)[_first[*_highest]]) {
453
+ _highest = _sets.back().end();
454
+ }
455
+ }
456
+ }
457
+ }
458
+
459
+ if ((*_excess)[target] < _min_cut) {
460
+ _min_cut = (*_excess)[target];
461
+ for (NodeIt i(_graph); i != INVALID; ++i) {
462
+ (*_min_cut_map)[i] = true;
463
+ }
464
+ for (std::list<int>::iterator it = _sets.back().begin();
465
+ it != _sets.back().end(); ++it) {
466
+ Node n = _first[*it];
467
+ while (n != INVALID) {
468
+ (*_min_cut_map)[n] = false;
469
+ n = (*_next)[n];
470
+ }
471
+ }
472
+ }
473
+
474
+ {
475
+ Node new_target;
476
+ if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
477
+ if ((*_next)[target] == INVALID) {
478
+ _last[(*_bucket)[target]] = (*_prev)[target];
479
+ new_target = (*_prev)[target];
480
+ } else {
481
+ (*_prev)[(*_next)[target]] = (*_prev)[target];
482
+ new_target = (*_next)[target];
483
+ }
484
+ if ((*_prev)[target] == INVALID) {
485
+ _first[(*_bucket)[target]] = (*_next)[target];
486
+ } else {
487
+ (*_next)[(*_prev)[target]] = (*_next)[target];
488
+ }
489
+ } else {
490
+ _sets.back().pop_back();
491
+ if (_sets.back().empty()) {
492
+ _sets.pop_back();
493
+ if (_sets.empty())
494
+ break;
495
+ for (std::list<int>::iterator it = _sets.back().begin();
496
+ it != _sets.back().end(); ++it) {
497
+ _dormant[*it] = false;
498
+ }
499
+ }
500
+ new_target = _last[_sets.back().back()];
501
+ }
502
+
503
+ (*_bucket)[target] = 0;
504
+
505
+ (*_source_set)[target] = true;
506
+ for (OutArcIt a(_graph, target); a != INVALID; ++a) {
507
+ Value rem = (*_capacity)[a] - (*_flow)[a];
508
+ if (!_tolerance.positive(rem)) continue;
509
+ Node v = _graph.target(a);
510
+ if (!(*_active)[v] && !(*_source_set)[v]) {
511
+ activate(v);
512
+ }
513
+ (*_excess)[v] += rem;
514
+ (*_flow)[a] = (*_capacity)[a];
515
+ }
516
+
517
+ for (InArcIt a(_graph, target); a != INVALID; ++a) {
518
+ Value rem = (*_flow)[a];
519
+ if (!_tolerance.positive(rem)) continue;
520
+ Node v = _graph.source(a);
521
+ if (!(*_active)[v] && !(*_source_set)[v]) {
522
+ activate(v);
523
+ }
524
+ (*_excess)[v] += rem;
525
+ (*_flow)[a] = 0;
526
+ }
527
+
528
+ target = new_target;
529
+ if ((*_active)[target]) {
530
+ deactivate(target);
531
+ }
532
+
533
+ _highest = _sets.back().begin();
534
+ while (_highest != _sets.back().end() &&
535
+ !(*_active)[_first[*_highest]]) {
536
+ ++_highest;
537
+ }
538
+ }
539
+ }
540
+ }
541
+
542
+ void findMinCutIn() {
543
+
544
+ for (NodeIt n(_graph); n != INVALID; ++n) {
545
+ (*_excess)[n] = 0;
546
+ (*_source_set)[n] = false;
547
+ }
548
+
549
+ for (ArcIt a(_graph); a != INVALID; ++a) {
550
+ (*_flow)[a] = 0;
551
+ }
552
+
553
+ int bucket_num = 0;
554
+ std::vector<Node> queue(_node_num);
555
+ int qfirst = 0, qlast = 0, qsep = 0;
556
+
557
+ {
558
+ typename Digraph::template NodeMap<bool> reached(_graph, false);
559
+
560
+ reached[_source] = true;
561
+
562
+ bool first_set = true;
563
+
564
+ for (NodeIt t(_graph); t != INVALID; ++t) {
565
+ if (reached[t]) continue;
566
+ _sets.push_front(std::list<int>());
567
+
568
+ queue[qlast++] = t;
569
+ reached[t] = true;
570
+
571
+ while (qfirst != qlast) {
572
+ if (qsep == qfirst) {
573
+ ++bucket_num;
574
+ _sets.front().push_front(bucket_num);
575
+ _dormant[bucket_num] = !first_set;
576
+ _first[bucket_num] = _last[bucket_num] = INVALID;
577
+ qsep = qlast;
578
+ }
579
+
580
+ Node n = queue[qfirst++];
581
+ addItem(n, bucket_num);
582
+
583
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
584
+ Node u = _graph.target(a);
585
+ if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
586
+ reached[u] = true;
587
+ queue[qlast++] = u;
588
+ }
589
+ }
590
+ }
591
+ first_set = false;
592
+ }
593
+
594
+ ++bucket_num;
595
+ (*_bucket)[_source] = 0;
596
+ _dormant[0] = true;
597
+ }
598
+ (*_source_set)[_source] = true;
599
+
600
+ Node target = _last[_sets.back().back()];
601
+ {
602
+ for (InArcIt a(_graph, _source); a != INVALID; ++a) {
603
+ if (_tolerance.positive((*_capacity)[a])) {
604
+ Node u = _graph.source(a);
605
+ (*_flow)[a] = (*_capacity)[a];
606
+ (*_excess)[u] += (*_capacity)[a];
607
+ if (!(*_active)[u] && u != _source) {
608
+ activate(u);
609
+ }
610
+ }
611
+ }
612
+ if ((*_active)[target]) {
613
+ deactivate(target);
614
+ }
615
+
616
+ _highest = _sets.back().begin();
617
+ while (_highest != _sets.back().end() &&
618
+ !(*_active)[_first[*_highest]]) {
619
+ ++_highest;
620
+ }
621
+ }
622
+
623
+
624
+ while (true) {
625
+ while (_highest != _sets.back().end()) {
626
+ Node n = _first[*_highest];
627
+ Value excess = (*_excess)[n];
628
+ int next_bucket = _node_num;
629
+
630
+ int under_bucket;
631
+ if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
632
+ under_bucket = -1;
633
+ } else {
634
+ under_bucket = *(++std::list<int>::iterator(_highest));
635
+ }
636
+
637
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
638
+ Node v = _graph.source(a);
639
+ if (_dormant[(*_bucket)[v]]) continue;
640
+ Value rem = (*_capacity)[a] - (*_flow)[a];
641
+ if (!_tolerance.positive(rem)) continue;
642
+ if ((*_bucket)[v] == under_bucket) {
643
+ if (!(*_active)[v] && v != target) {
644
+ activate(v);
645
+ }
646
+ if (!_tolerance.less(rem, excess)) {
647
+ (*_flow)[a] += excess;
648
+ (*_excess)[v] += excess;
649
+ excess = 0;
650
+ goto no_more_push;
651
+ } else {
652
+ excess -= rem;
653
+ (*_excess)[v] += rem;
654
+ (*_flow)[a] = (*_capacity)[a];
655
+ }
656
+ } else if (next_bucket > (*_bucket)[v]) {
657
+ next_bucket = (*_bucket)[v];
658
+ }
659
+ }
660
+
661
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
662
+ Node v = _graph.target(a);
663
+ if (_dormant[(*_bucket)[v]]) continue;
664
+ Value rem = (*_flow)[a];
665
+ if (!_tolerance.positive(rem)) continue;
666
+ if ((*_bucket)[v] == under_bucket) {
667
+ if (!(*_active)[v] && v != target) {
668
+ activate(v);
669
+ }
670
+ if (!_tolerance.less(rem, excess)) {
671
+ (*_flow)[a] -= excess;
672
+ (*_excess)[v] += excess;
673
+ excess = 0;
674
+ goto no_more_push;
675
+ } else {
676
+ excess -= rem;
677
+ (*_excess)[v] += rem;
678
+ (*_flow)[a] = 0;
679
+ }
680
+ } else if (next_bucket > (*_bucket)[v]) {
681
+ next_bucket = (*_bucket)[v];
682
+ }
683
+ }
684
+
685
+ no_more_push:
686
+
687
+ (*_excess)[n] = excess;
688
+
689
+ if (excess != 0) {
690
+ if ((*_next)[n] == INVALID) {
691
+ typename std::list<std::list<int> >::iterator new_set =
692
+ _sets.insert(--_sets.end(), std::list<int>());
693
+ new_set->splice(new_set->end(), _sets.back(),
694
+ _sets.back().begin(), ++_highest);
695
+ for (std::list<int>::iterator it = new_set->begin();
696
+ it != new_set->end(); ++it) {
697
+ _dormant[*it] = true;
698
+ }
699
+ while (_highest != _sets.back().end() &&
700
+ !(*_active)[_first[*_highest]]) {
701
+ ++_highest;
702
+ }
703
+ } else if (next_bucket == _node_num) {
704
+ _first[(*_bucket)[n]] = (*_next)[n];
705
+ (*_prev)[(*_next)[n]] = INVALID;
706
+
707
+ std::list<std::list<int> >::iterator new_set =
708
+ _sets.insert(--_sets.end(), std::list<int>());
709
+
710
+ new_set->push_front(bucket_num);
711
+ (*_bucket)[n] = bucket_num;
712
+ _first[bucket_num] = _last[bucket_num] = n;
713
+ (*_next)[n] = INVALID;
714
+ (*_prev)[n] = INVALID;
715
+ _dormant[bucket_num] = true;
716
+ ++bucket_num;
717
+
718
+ while (_highest != _sets.back().end() &&
719
+ !(*_active)[_first[*_highest]]) {
720
+ ++_highest;
721
+ }
722
+ } else {
723
+ _first[*_highest] = (*_next)[n];
724
+ (*_prev)[(*_next)[n]] = INVALID;
725
+
726
+ while (next_bucket != *_highest) {
727
+ --_highest;
728
+ }
729
+ if (_highest == _sets.back().begin()) {
730
+ _sets.back().push_front(bucket_num);
731
+ _dormant[bucket_num] = false;
732
+ _first[bucket_num] = _last[bucket_num] = INVALID;
733
+ ++bucket_num;
734
+ }
735
+ --_highest;
736
+
737
+ (*_bucket)[n] = *_highest;
738
+ (*_next)[n] = _first[*_highest];
739
+ if (_first[*_highest] != INVALID) {
740
+ (*_prev)[_first[*_highest]] = n;
741
+ } else {
742
+ _last[*_highest] = n;
743
+ }
744
+ _first[*_highest] = n;
745
+ }
746
+ } else {
747
+
748
+ deactivate(n);
749
+ if (!(*_active)[_first[*_highest]]) {
750
+ ++_highest;
751
+ if (_highest != _sets.back().end() &&
752
+ !(*_active)[_first[*_highest]]) {
753
+ _highest = _sets.back().end();
754
+ }
755
+ }
756
+ }
757
+ }
758
+
759
+ if ((*_excess)[target] < _min_cut) {
760
+ _min_cut = (*_excess)[target];
761
+ for (NodeIt i(_graph); i != INVALID; ++i) {
762
+ (*_min_cut_map)[i] = false;
763
+ }
764
+ for (std::list<int>::iterator it = _sets.back().begin();
765
+ it != _sets.back().end(); ++it) {
766
+ Node n = _first[*it];
767
+ while (n != INVALID) {
768
+ (*_min_cut_map)[n] = true;
769
+ n = (*_next)[n];
770
+ }
771
+ }
772
+ }
773
+
774
+ {
775
+ Node new_target;
776
+ if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
777
+ if ((*_next)[target] == INVALID) {
778
+ _last[(*_bucket)[target]] = (*_prev)[target];
779
+ new_target = (*_prev)[target];
780
+ } else {
781
+ (*_prev)[(*_next)[target]] = (*_prev)[target];
782
+ new_target = (*_next)[target];
783
+ }
784
+ if ((*_prev)[target] == INVALID) {
785
+ _first[(*_bucket)[target]] = (*_next)[target];
786
+ } else {
787
+ (*_next)[(*_prev)[target]] = (*_next)[target];
788
+ }
789
+ } else {
790
+ _sets.back().pop_back();
791
+ if (_sets.back().empty()) {
792
+ _sets.pop_back();
793
+ if (_sets.empty())
794
+ break;
795
+ for (std::list<int>::iterator it = _sets.back().begin();
796
+ it != _sets.back().end(); ++it) {
797
+ _dormant[*it] = false;
798
+ }
799
+ }
800
+ new_target = _last[_sets.back().back()];
801
+ }
802
+
803
+ (*_bucket)[target] = 0;
804
+
805
+ (*_source_set)[target] = true;
806
+ for (InArcIt a(_graph, target); a != INVALID; ++a) {
807
+ Value rem = (*_capacity)[a] - (*_flow)[a];
808
+ if (!_tolerance.positive(rem)) continue;
809
+ Node v = _graph.source(a);
810
+ if (!(*_active)[v] && !(*_source_set)[v]) {
811
+ activate(v);
812
+ }
813
+ (*_excess)[v] += rem;
814
+ (*_flow)[a] = (*_capacity)[a];
815
+ }
816
+
817
+ for (OutArcIt a(_graph, target); a != INVALID; ++a) {
818
+ Value rem = (*_flow)[a];
819
+ if (!_tolerance.positive(rem)) continue;
820
+ Node v = _graph.target(a);
821
+ if (!(*_active)[v] && !(*_source_set)[v]) {
822
+ activate(v);
823
+ }
824
+ (*_excess)[v] += rem;
825
+ (*_flow)[a] = 0;
826
+ }
827
+
828
+ target = new_target;
829
+ if ((*_active)[target]) {
830
+ deactivate(target);
831
+ }
832
+
833
+ _highest = _sets.back().begin();
834
+ while (_highest != _sets.back().end() &&
835
+ !(*_active)[_first[*_highest]]) {
836
+ ++_highest;
837
+ }
838
+ }
839
+ }
840
+ }
841
+
842
+ public:
843
+
844
+ /// \name Execution Control
845
+ /// The simplest way to execute the algorithm is to use
846
+ /// one of the member functions called \ref run().
847
+ /// \n
848
+ /// If you need better control on the execution,
849
+ /// you have to call one of the \ref init() functions first, then
850
+ /// \ref calculateOut() and/or \ref calculateIn().
851
+
852
+ /// @{
853
+
854
+ /// \brief Initialize the internal data structures.
855
+ ///
856
+ /// This function initializes the internal data structures. It creates
857
+ /// the maps and some bucket structures for the algorithm.
858
+ /// The first node is used as the source node for the push-relabel
859
+ /// algorithm.
860
+ void init() {
861
+ init(NodeIt(_graph));
862
+ }
863
+
864
+ /// \brief Initialize the internal data structures.
865
+ ///
866
+ /// This function initializes the internal data structures. It creates
867
+ /// the maps and some bucket structures for the algorithm.
868
+ /// The given node is used as the source node for the push-relabel
869
+ /// algorithm.
870
+ void init(const Node& source) {
871
+ _source = source;
872
+
873
+ _node_num = countNodes(_graph);
874
+
875
+ _first.resize(_node_num);
876
+ _last.resize(_node_num);
877
+
878
+ _dormant.resize(_node_num);
879
+
880
+ if (!_flow) {
881
+ _flow = new FlowMap(_graph);
882
+ }
883
+ if (!_next) {
884
+ _next = new typename Digraph::template NodeMap<Node>(_graph);
885
+ }
886
+ if (!_prev) {
887
+ _prev = new typename Digraph::template NodeMap<Node>(_graph);
888
+ }
889
+ if (!_active) {
890
+ _active = new typename Digraph::template NodeMap<bool>(_graph);
891
+ }
892
+ if (!_bucket) {
893
+ _bucket = new typename Digraph::template NodeMap<int>(_graph);
894
+ }
895
+ if (!_excess) {
896
+ _excess = new ExcessMap(_graph);
897
+ }
898
+ if (!_source_set) {
899
+ _source_set = new SourceSetMap(_graph);
900
+ }
901
+ if (!_min_cut_map) {
902
+ _min_cut_map = new MinCutMap(_graph);
903
+ }
904
+
905
+ _min_cut = std::numeric_limits<Value>::max();
906
+ }
907
+
908
+
909
+ /// \brief Calculate a minimum cut with \f$ source \f$ on the
910
+ /// source-side.
911
+ ///
912
+ /// This function calculates a minimum cut with \f$ source \f$ on the
913
+ /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
914
+ /// \f$ source \in X \f$ and minimal outgoing capacity).
915
+ /// It updates the stored cut if (and only if) the newly found one
916
+ /// is better.
917
+ ///
918
+ /// \pre \ref init() must be called before using this function.
919
+ void calculateOut() {
920
+ findMinCutOut();
921
+ }
922
+
923
+ /// \brief Calculate a minimum cut with \f$ source \f$ on the
924
+ /// sink-side.
925
+ ///
926
+ /// This function calculates a minimum cut with \f$ source \f$ on the
927
+ /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
928
+ /// \f$ source \notin X \f$ and minimal outgoing capacity).
929
+ /// It updates the stored cut if (and only if) the newly found one
930
+ /// is better.
931
+ ///
932
+ /// \pre \ref init() must be called before using this function.
933
+ void calculateIn() {
934
+ findMinCutIn();
935
+ }
936
+
937
+
938
+ /// \brief Run the algorithm.
939
+ ///
940
+ /// This function runs the algorithm. It chooses source node,
941
+ /// then calls \ref init(), \ref calculateOut()
942
+ /// and \ref calculateIn().
943
+ void run() {
944
+ init();
945
+ calculateOut();
946
+ calculateIn();
947
+ }
948
+
949
+ /// \brief Run the algorithm.
950
+ ///
951
+ /// This function runs the algorithm. It calls \ref init(),
952
+ /// \ref calculateOut() and \ref calculateIn() with the given
953
+ /// source node.
954
+ void run(const Node& s) {
955
+ init(s);
956
+ calculateOut();
957
+ calculateIn();
958
+ }
959
+
960
+ /// @}
961
+
962
+ /// \name Query Functions
963
+ /// The result of the %HaoOrlin algorithm
964
+ /// can be obtained using these functions.\n
965
+ /// \ref run(), \ref calculateOut() or \ref calculateIn()
966
+ /// should be called before using them.
967
+
968
+ /// @{
969
+
970
+ /// \brief Return the value of the minimum cut.
971
+ ///
972
+ /// This function returns the value of the best cut found by the
973
+ /// previously called \ref run(), \ref calculateOut() or \ref
974
+ /// calculateIn().
975
+ ///
976
+ /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
977
+ /// must be called before using this function.
978
+ Value minCutValue() const {
979
+ return _min_cut;
980
+ }
981
+
982
+
983
+ /// \brief Return a minimum cut.
984
+ ///
985
+ /// This function gives the best cut found by the
986
+ /// previously called \ref run(), \ref calculateOut() or \ref
987
+ /// calculateIn().
988
+ ///
989
+ /// It sets \c cutMap to the characteristic vector of the found
990
+ /// minimum value cut - a non-empty set \f$ X\subsetneq V \f$
991
+ /// of minimum outgoing capacity (i.e. \c cutMap will be \c true exactly
992
+ /// for the nodes of \f$ X \f$).
993
+ ///
994
+ /// \param cutMap A \ref concepts::WriteMap "writable" node map with
995
+ /// \c bool (or convertible) value type.
996
+ ///
997
+ /// \return The value of the minimum cut.
998
+ ///
999
+ /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
1000
+ /// must be called before using this function.
1001
+ template <typename CutMap>
1002
+ Value minCutMap(CutMap& cutMap) const {
1003
+ for (NodeIt it(_graph); it != INVALID; ++it) {
1004
+ cutMap.set(it, (*_min_cut_map)[it]);
1005
+ }
1006
+ return _min_cut;
1007
+ }
1008
+
1009
+ /// @}
1010
+
1011
+ }; //class HaoOrlin
1012
+
1013
+ } //namespace lemon
1014
+
1015
+ #endif //LEMON_HAO_ORLIN_H