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.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/ext/lemon-1.3.1/AUTHORS +26 -0
- data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
- data/ext/lemon-1.3.1/INSTALL +167 -0
- data/ext/lemon-1.3.1/LICENSE +32 -0
- data/ext/lemon-1.3.1/NEWS +337 -0
- data/ext/lemon-1.3.1/README +50 -0
- data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
- data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
- data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
- data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
- data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
- data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
- data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
- data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
- data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
- data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
- data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
- data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
- data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
- data/ext/lemon-1.3.1/lemon/assert.h +214 -0
- data/ext/lemon-1.3.1/lemon/base.cc +37 -0
- data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
- data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
- data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
- data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
- data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
- data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
- data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
- data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
- data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
- data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
- data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
- data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
- data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
- data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
- data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
- data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
- data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
- data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
- data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
- data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
- data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
- data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
- data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
- data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
- data/ext/lemon-1.3.1/lemon/clp.h +164 -0
- data/ext/lemon-1.3.1/lemon/color.cc +44 -0
- data/ext/lemon-1.3.1/lemon/color.h +204 -0
- data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
- data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
- data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
- data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
- data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
- data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
- data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
- data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
- data/ext/lemon-1.3.1/lemon/core.h +2506 -0
- data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
- data/ext/lemon-1.3.1/lemon/counter.h +249 -0
- data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
- data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
- data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
- data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
- data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
- data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
- data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
- data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
- data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
- data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
- data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
- data/ext/lemon-1.3.1/lemon/error.h +276 -0
- data/ext/lemon-1.3.1/lemon/euler.h +287 -0
- data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
- data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
- data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
- data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
- data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
- data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
- data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
- data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
- data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
- data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
- data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
- data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
- data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
- data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
- data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
- data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
- data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
- data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
- data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
- data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
- data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
- data/ext/lemon-1.3.1/lemon/lp.h +95 -0
- data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
- data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
- data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
- data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
- data/ext/lemon-1.3.1/lemon/math.h +77 -0
- data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
- data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
- data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
- data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
- data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
- data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
- data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
- data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
- data/ext/lemon-1.3.1/lemon/path.h +1164 -0
- data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
- data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
- data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
- data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
- data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
- data/ext/lemon-1.3.1/lemon/random.cc +29 -0
- data/ext/lemon-1.3.1/lemon/random.h +1005 -0
- data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
- data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
- data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
- data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
- data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
- data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
- data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
- data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
- data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
- data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
- data/ext/lemongraph/arc_map.cc +1007 -0
- data/ext/lemongraph/digraph.cc +282 -0
- data/ext/lemongraph/digraph_arc.cc +153 -0
- data/ext/lemongraph/digraph_node.cc +277 -0
- data/ext/lemongraph/edge_map.cc +770 -0
- data/ext/lemongraph/extconf.rb +53 -0
- data/ext/lemongraph/graph.cc +351 -0
- data/ext/lemongraph/graph_arc.cc +95 -0
- data/ext/lemongraph/graph_edge.cc +153 -0
- data/ext/lemongraph/graph_item.cc +76 -0
- data/ext/lemongraph/graph_node.cc +321 -0
- data/ext/lemongraph/lemongraph.cc +260 -0
- data/ext/lemongraph/lemongraph.hh +295 -0
- data/ext/lemongraph/lemongraph.map +6 -0
- data/ext/lemongraph/lemongraph_export.hh +31 -0
- data/ext/lemongraph/node_map.cc +1011 -0
- data/lemongraph.gemspec +176 -0
- data/lib/lemongraph/graphviz.rb +240 -0
- data/lib/lemongraph/version.rb +4 -0
- data/lib/lemongraph.rb +21 -0
- data/samples/lemondeps.rb +38 -0
- 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
|