deba@2211
|
1 |
/* -*- C++ -*-
|
deba@2211
|
2 |
* lemon/hao_orlin.h - Part of LEMON, a generic C++ optimization library
|
deba@2211
|
3 |
*
|
deba@2211
|
4 |
* Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
deba@2211
|
5 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
deba@2211
|
6 |
*
|
deba@2211
|
7 |
* Permission to use, modify and distribute this software is granted
|
deba@2211
|
8 |
* provided that this copyright notice appears in all copies. For
|
deba@2211
|
9 |
* precise terms see the accompanying LICENSE file.
|
deba@2211
|
10 |
*
|
deba@2211
|
11 |
* This software is provided "AS IS" with no warranty of any kind,
|
deba@2211
|
12 |
* express or implied, and with no claim as to its suitability for any
|
deba@2211
|
13 |
* purpose.
|
deba@2211
|
14 |
*
|
deba@2211
|
15 |
*/
|
deba@2211
|
16 |
|
deba@2211
|
17 |
#ifndef LEMON_HAO_ORLIN_H
|
deba@2211
|
18 |
#define LEMON_HAO_ORLIN_H
|
deba@2211
|
19 |
|
deba@2211
|
20 |
#include <vector>
|
deba@2211
|
21 |
#include <queue>
|
deba@2211
|
22 |
#include <limits>
|
deba@2211
|
23 |
|
deba@2211
|
24 |
#include <lemon/maps.h>
|
deba@2211
|
25 |
#include <lemon/graph_utils.h>
|
deba@2211
|
26 |
#include <lemon/graph_adaptor.h>
|
deba@2211
|
27 |
#include <lemon/iterable_maps.h>
|
deba@2211
|
28 |
|
deba@2211
|
29 |
|
deba@2211
|
30 |
/// \file
|
deba@2211
|
31 |
/// \ingroup flowalgs
|
deba@2211
|
32 |
/// Implementation of the Hao-Orlin algorithms class for testing network
|
deba@2211
|
33 |
/// reliability.
|
deba@2211
|
34 |
|
deba@2211
|
35 |
namespace lemon {
|
deba@2211
|
36 |
|
deba@2211
|
37 |
/// \addtogroup flowalgs
|
deba@2211
|
38 |
/// @{
|
deba@2211
|
39 |
|
deba@2211
|
40 |
/// %Hao-Orlin algorithm for calculate minimum cut in directed graphs.
|
deba@2211
|
41 |
///
|
deba@2211
|
42 |
/// Hao-Orlin calculates the minimum cut in directed graphs. It
|
deba@2211
|
43 |
/// separates the nodes of the graph into two disjoint sets and the
|
deba@2211
|
44 |
/// summary of the edge capacities go from the first set to the
|
deba@2211
|
45 |
/// second set is the minimum. The algorithm is a modified
|
deba@2211
|
46 |
/// push-relabel preflow algorithm and it calculates the minimum cat
|
deba@2211
|
47 |
/// in \f$ O(n^3) \f$ time. The purpose of such algorithm is testing
|
deba@2211
|
48 |
/// network reliability. For sparse undirected graph you can use the
|
deba@2211
|
49 |
/// algorithm of Nagamochi and Ibraki which solves the undirected
|
deba@2211
|
50 |
/// problem in \f$ O(n^3) \f$ time.
|
deba@2211
|
51 |
///
|
deba@2211
|
52 |
/// \author Attila Bernath and Balazs Dezso
|
deba@2211
|
53 |
template <typename _Graph,
|
deba@2211
|
54 |
typename _CapacityMap = typename _Graph::template EdgeMap<int>,
|
deba@2211
|
55 |
typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
|
deba@2211
|
56 |
class HaoOrlin {
|
deba@2211
|
57 |
protected:
|
deba@2211
|
58 |
|
deba@2211
|
59 |
typedef _Graph Graph;
|
deba@2211
|
60 |
typedef _CapacityMap CapacityMap;
|
deba@2211
|
61 |
typedef _Tolerance Tolerance;
|
deba@2211
|
62 |
|
deba@2211
|
63 |
typedef typename CapacityMap::Value Value;
|
deba@2211
|
64 |
|
deba@2211
|
65 |
|
deba@2211
|
66 |
typedef typename Graph::Node Node;
|
deba@2211
|
67 |
typedef typename Graph::NodeIt NodeIt;
|
deba@2211
|
68 |
typedef typename Graph::EdgeIt EdgeIt;
|
deba@2211
|
69 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
deba@2211
|
70 |
typedef typename Graph::InEdgeIt InEdgeIt;
|
deba@2211
|
71 |
|
deba@2211
|
72 |
const Graph* _graph;
|
deba@2211
|
73 |
const CapacityMap* _capacity;
|
deba@2211
|
74 |
|
deba@2211
|
75 |
typedef typename Graph::template EdgeMap<Value> FlowMap;
|
deba@2211
|
76 |
|
deba@2211
|
77 |
FlowMap* _preflow;
|
deba@2211
|
78 |
|
deba@2211
|
79 |
Node _source, _target;
|
deba@2211
|
80 |
int _node_num;
|
deba@2211
|
81 |
|
deba@2211
|
82 |
typedef ResGraphAdaptor<const Graph, Value, CapacityMap,
|
deba@2211
|
83 |
FlowMap, Tolerance> ResGraph;
|
deba@2211
|
84 |
typedef typename ResGraph::Node ResNode;
|
deba@2211
|
85 |
typedef typename ResGraph::NodeIt ResNodeIt;
|
deba@2211
|
86 |
typedef typename ResGraph::EdgeIt ResEdgeIt;
|
deba@2211
|
87 |
typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
|
deba@2211
|
88 |
typedef typename ResGraph::Edge ResEdge;
|
deba@2211
|
89 |
typedef typename ResGraph::InEdgeIt ResInEdgeIt;
|
deba@2211
|
90 |
|
deba@2211
|
91 |
ResGraph* _res_graph;
|
deba@2211
|
92 |
|
deba@2211
|
93 |
typedef typename Graph::template NodeMap<ResEdge> CurrentArcMap;
|
deba@2211
|
94 |
CurrentArcMap* _current_arc;
|
deba@2211
|
95 |
|
deba@2211
|
96 |
|
deba@2211
|
97 |
typedef IterableBoolMap<Graph, Node> WakeMap;
|
deba@2211
|
98 |
WakeMap* _wake;
|
deba@2211
|
99 |
|
deba@2211
|
100 |
typedef typename Graph::template NodeMap<int> DistMap;
|
deba@2211
|
101 |
DistMap* _dist;
|
deba@2211
|
102 |
|
deba@2211
|
103 |
typedef typename Graph::template NodeMap<Value> ExcessMap;
|
deba@2211
|
104 |
ExcessMap* _excess;
|
deba@2211
|
105 |
|
deba@2211
|
106 |
typedef typename Graph::template NodeMap<bool> SourceSetMap;
|
deba@2211
|
107 |
SourceSetMap* _source_set;
|
deba@2211
|
108 |
|
deba@2211
|
109 |
std::vector<int> _level_size;
|
deba@2211
|
110 |
|
deba@2211
|
111 |
int _highest_active;
|
deba@2211
|
112 |
std::vector<std::list<Node> > _active_nodes;
|
deba@2211
|
113 |
|
deba@2211
|
114 |
int _dormant_max;
|
deba@2211
|
115 |
std::vector<std::list<Node> > _dormant;
|
deba@2211
|
116 |
|
deba@2211
|
117 |
|
deba@2211
|
118 |
Value _min_cut;
|
deba@2211
|
119 |
|
deba@2211
|
120 |
typedef typename Graph::template NodeMap<bool> MinCutMap;
|
deba@2211
|
121 |
MinCutMap* _min_cut_map;
|
deba@2211
|
122 |
|
deba@2211
|
123 |
Tolerance _tolerance;
|
deba@2211
|
124 |
|
deba@2211
|
125 |
public:
|
deba@2211
|
126 |
|
deba@2211
|
127 |
HaoOrlin(const Graph& graph, const CapacityMap& capacity,
|
deba@2211
|
128 |
const Tolerance& tolerance = Tolerance()) :
|
deba@2211
|
129 |
_graph(&graph), _capacity(&capacity),
|
deba@2211
|
130 |
_preflow(0), _source(), _target(), _res_graph(0), _current_arc(0),
|
deba@2211
|
131 |
_wake(0),_dist(0), _excess(0), _source_set(0),
|
deba@2211
|
132 |
_highest_active(), _active_nodes(), _dormant_max(), _dormant(),
|
deba@2211
|
133 |
_min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
|
deba@2211
|
134 |
|
deba@2211
|
135 |
~HaoOrlin() {
|
deba@2211
|
136 |
if (_res_graph) {
|
deba@2211
|
137 |
delete _res_graph;
|
deba@2211
|
138 |
}
|
deba@2211
|
139 |
if (_min_cut_map) {
|
deba@2211
|
140 |
delete _min_cut_map;
|
deba@2211
|
141 |
}
|
deba@2211
|
142 |
if (_current_arc) {
|
deba@2211
|
143 |
delete _current_arc;
|
deba@2211
|
144 |
}
|
deba@2211
|
145 |
if (_source_set) {
|
deba@2211
|
146 |
delete _source_set;
|
deba@2211
|
147 |
}
|
deba@2211
|
148 |
if (_excess) {
|
deba@2211
|
149 |
delete _excess;
|
deba@2211
|
150 |
}
|
deba@2211
|
151 |
if (_dist) {
|
deba@2211
|
152 |
delete _dist;
|
deba@2211
|
153 |
}
|
deba@2211
|
154 |
if (_wake) {
|
deba@2211
|
155 |
delete _wake;
|
deba@2211
|
156 |
}
|
deba@2211
|
157 |
if (_preflow) {
|
deba@2211
|
158 |
delete _preflow;
|
deba@2211
|
159 |
}
|
deba@2211
|
160 |
}
|
deba@2211
|
161 |
|
deba@2211
|
162 |
private:
|
deba@2211
|
163 |
|
deba@2211
|
164 |
void relabel(Node i) {
|
deba@2211
|
165 |
int k = (*_dist)[i];
|
deba@2211
|
166 |
if (_level_size[k] == 1) {
|
deba@2211
|
167 |
++_dormant_max;
|
deba@2211
|
168 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
169 |
if ((*_wake)[it] && (*_dist)[it] >= k) {
|
deba@2211
|
170 |
(*_wake)[it] = false;
|
deba@2211
|
171 |
_dormant[_dormant_max].push_front(it);
|
deba@2211
|
172 |
--_level_size[(*_dist)[it]];
|
deba@2211
|
173 |
}
|
deba@2211
|
174 |
}
|
deba@2211
|
175 |
--_highest_active;
|
deba@2211
|
176 |
} else {
|
deba@2211
|
177 |
ResOutEdgeIt e(*_res_graph, i);
|
deba@2211
|
178 |
while (e != INVALID && !(*_wake)[_res_graph->target(e)]) {
|
deba@2211
|
179 |
++e;
|
deba@2211
|
180 |
}
|
deba@2211
|
181 |
|
deba@2211
|
182 |
if (e == INVALID){
|
deba@2211
|
183 |
++_dormant_max;
|
deba@2211
|
184 |
(*_wake)[i] = false;
|
deba@2211
|
185 |
_dormant[_dormant_max].push_front(i);
|
deba@2211
|
186 |
--_level_size[(*_dist)[i]];
|
deba@2211
|
187 |
} else{
|
deba@2211
|
188 |
Node j = _res_graph->target(e);
|
deba@2211
|
189 |
int new_dist = (*_dist)[j];
|
deba@2211
|
190 |
++e;
|
deba@2211
|
191 |
while (e != INVALID){
|
deba@2211
|
192 |
Node j = _res_graph->target(e);
|
deba@2211
|
193 |
if ((*_wake)[j] && new_dist > (*_dist)[j]) {
|
deba@2211
|
194 |
new_dist = (*_dist)[j];
|
deba@2211
|
195 |
}
|
deba@2211
|
196 |
++e;
|
deba@2211
|
197 |
}
|
deba@2211
|
198 |
--_level_size[(*_dist)[i]];
|
deba@2211
|
199 |
(*_dist)[i] = new_dist + 1;
|
deba@2211
|
200 |
_highest_active = (*_dist)[i];
|
deba@2211
|
201 |
_active_nodes[_highest_active].push_front(i);
|
deba@2211
|
202 |
++_level_size[(*_dist)[i]];
|
deba@2211
|
203 |
_res_graph->firstOut((*_current_arc)[i], i);
|
deba@2211
|
204 |
}
|
deba@2211
|
205 |
}
|
deba@2211
|
206 |
}
|
deba@2211
|
207 |
|
deba@2211
|
208 |
bool selectNewSink(){
|
deba@2211
|
209 |
Node old_target = _target;
|
deba@2211
|
210 |
(*_wake)[_target] = false;
|
deba@2211
|
211 |
--_level_size[(*_dist)[_target]];
|
deba@2211
|
212 |
_dormant[0].push_front(_target);
|
deba@2211
|
213 |
(*_source_set)[_target] = true;
|
deba@2211
|
214 |
if ((int)_dormant[0].size() == _node_num){
|
deba@2211
|
215 |
_dormant[0].clear();
|
deba@2211
|
216 |
return false;
|
deba@2211
|
217 |
}
|
deba@2211
|
218 |
|
deba@2211
|
219 |
bool wake_was_empty = false;
|
deba@2211
|
220 |
|
deba@2211
|
221 |
if(_wake->trueNum() == 0) {
|
deba@2211
|
222 |
while (!_dormant[_dormant_max].empty()){
|
deba@2211
|
223 |
(*_wake)[_dormant[_dormant_max].front()] = true;
|
deba@2211
|
224 |
++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
|
deba@2211
|
225 |
_dormant[_dormant_max].pop_front();
|
deba@2211
|
226 |
}
|
deba@2211
|
227 |
--_dormant_max;
|
deba@2211
|
228 |
wake_was_empty = true;
|
deba@2211
|
229 |
}
|
deba@2211
|
230 |
|
deba@2211
|
231 |
int min_dist = std::numeric_limits<int>::max();
|
deba@2211
|
232 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2211
|
233 |
if (min_dist > (*_dist)[it]){
|
deba@2211
|
234 |
_target = it;
|
deba@2211
|
235 |
min_dist = (*_dist)[it];
|
deba@2211
|
236 |
}
|
deba@2211
|
237 |
}
|
deba@2211
|
238 |
|
deba@2211
|
239 |
if (wake_was_empty){
|
deba@2211
|
240 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2211
|
241 |
if (_tolerance.positive((*_excess)[it])) {
|
deba@2211
|
242 |
if ((*_wake)[it] && it != _target) {
|
deba@2211
|
243 |
_active_nodes[(*_dist)[it]].push_front(it);
|
deba@2211
|
244 |
}
|
deba@2211
|
245 |
if (_highest_active < (*_dist)[it]) {
|
deba@2211
|
246 |
_highest_active = (*_dist)[it];
|
deba@2211
|
247 |
}
|
deba@2211
|
248 |
}
|
deba@2211
|
249 |
}
|
deba@2211
|
250 |
}
|
deba@2211
|
251 |
|
deba@2211
|
252 |
for (ResOutEdgeIt e(*_res_graph, old_target); e!=INVALID; ++e){
|
deba@2211
|
253 |
if (!(*_source_set)[_res_graph->target(e)]){
|
deba@2211
|
254 |
push(e, _res_graph->rescap(e));
|
deba@2211
|
255 |
}
|
deba@2211
|
256 |
}
|
deba@2211
|
257 |
|
deba@2211
|
258 |
return true;
|
deba@2211
|
259 |
}
|
deba@2211
|
260 |
|
deba@2211
|
261 |
Node findActiveNode() {
|
deba@2211
|
262 |
while (_highest_active > 0 && _active_nodes[_highest_active].empty()){
|
deba@2211
|
263 |
--_highest_active;
|
deba@2211
|
264 |
}
|
deba@2211
|
265 |
if( _highest_active > 0) {
|
deba@2211
|
266 |
Node n = _active_nodes[_highest_active].front();
|
deba@2211
|
267 |
_active_nodes[_highest_active].pop_front();
|
deba@2211
|
268 |
return n;
|
deba@2211
|
269 |
} else {
|
deba@2211
|
270 |
return INVALID;
|
deba@2211
|
271 |
}
|
deba@2211
|
272 |
}
|
deba@2211
|
273 |
|
deba@2211
|
274 |
ResEdge findAdmissibleEdge(const Node& n){
|
deba@2211
|
275 |
ResEdge e = (*_current_arc)[n];
|
deba@2211
|
276 |
while (e != INVALID &&
|
deba@2211
|
277 |
((*_dist)[n] <= (*_dist)[_res_graph->target(e)] ||
|
deba@2211
|
278 |
!(*_wake)[_res_graph->target(e)])) {
|
deba@2211
|
279 |
_res_graph->nextOut(e);
|
deba@2211
|
280 |
}
|
deba@2211
|
281 |
if (e != INVALID) {
|
deba@2211
|
282 |
(*_current_arc)[n] = e;
|
deba@2211
|
283 |
return e;
|
deba@2211
|
284 |
} else {
|
deba@2211
|
285 |
return INVALID;
|
deba@2211
|
286 |
}
|
deba@2211
|
287 |
}
|
deba@2211
|
288 |
|
deba@2211
|
289 |
void push(ResEdge& e,const Value& delta){
|
deba@2211
|
290 |
_res_graph->augment(e, delta);
|
deba@2211
|
291 |
if (!_tolerance.positive(delta)) return;
|
deba@2211
|
292 |
|
deba@2211
|
293 |
(*_excess)[_res_graph->source(e)] -= delta;
|
deba@2211
|
294 |
Node a = _res_graph->target(e);
|
deba@2211
|
295 |
if (!_tolerance.positive((*_excess)[a]) && (*_wake)[a] && a != _target) {
|
deba@2211
|
296 |
_active_nodes[(*_dist)[a]].push_front(a);
|
deba@2211
|
297 |
if (_highest_active < (*_dist)[a]) {
|
deba@2211
|
298 |
_highest_active = (*_dist)[a];
|
deba@2211
|
299 |
}
|
deba@2211
|
300 |
}
|
deba@2211
|
301 |
(*_excess)[a] += delta;
|
deba@2211
|
302 |
}
|
deba@2211
|
303 |
|
deba@2211
|
304 |
Value cutValue() {
|
deba@2211
|
305 |
Value value = 0;
|
deba@2211
|
306 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2211
|
307 |
for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
|
deba@2211
|
308 |
if (!(*_wake)[_graph->source(e)]){
|
deba@2211
|
309 |
value += (*_capacity)[e];
|
deba@2211
|
310 |
}
|
deba@2211
|
311 |
}
|
deba@2211
|
312 |
}
|
deba@2211
|
313 |
return value;
|
deba@2211
|
314 |
}
|
deba@2211
|
315 |
|
deba@2211
|
316 |
public:
|
deba@2211
|
317 |
|
deba@2211
|
318 |
/// \brief Initializes the internal data structures.
|
deba@2211
|
319 |
///
|
deba@2211
|
320 |
/// Initializes the internal data structures. It creates
|
deba@2211
|
321 |
/// the maps, residual graph adaptor and some bucket structures
|
deba@2211
|
322 |
/// for the algorithm.
|
deba@2211
|
323 |
void init() {
|
deba@2211
|
324 |
init(NodeIt(*_graph));
|
deba@2211
|
325 |
}
|
deba@2211
|
326 |
|
deba@2211
|
327 |
/// \brief Initializes the internal data structures.
|
deba@2211
|
328 |
///
|
deba@2211
|
329 |
/// Initializes the internal data structures. It creates
|
deba@2211
|
330 |
/// the maps, residual graph adaptor and some bucket structures
|
deba@2211
|
331 |
/// for the algorithm. The \c source node is used as the push-relabel
|
deba@2211
|
332 |
/// algorithm's source.
|
deba@2211
|
333 |
void init(const Node& source) {
|
deba@2211
|
334 |
_source = source;
|
deba@2211
|
335 |
_node_num = countNodes(*_graph);
|
deba@2211
|
336 |
|
deba@2211
|
337 |
_dormant.resize(_node_num);
|
deba@2211
|
338 |
_level_size.resize(_node_num, 0);
|
deba@2211
|
339 |
_active_nodes.resize(_node_num);
|
deba@2211
|
340 |
|
deba@2211
|
341 |
if (!_preflow) {
|
deba@2211
|
342 |
_preflow = new FlowMap(*_graph);
|
deba@2211
|
343 |
}
|
deba@2211
|
344 |
if (!_wake) {
|
deba@2211
|
345 |
_wake = new WakeMap(*_graph);
|
deba@2211
|
346 |
}
|
deba@2211
|
347 |
if (!_dist) {
|
deba@2211
|
348 |
_dist = new DistMap(*_graph);
|
deba@2211
|
349 |
}
|
deba@2211
|
350 |
if (!_excess) {
|
deba@2211
|
351 |
_excess = new ExcessMap(*_graph);
|
deba@2211
|
352 |
}
|
deba@2211
|
353 |
if (!_source_set) {
|
deba@2211
|
354 |
_source_set = new SourceSetMap(*_graph);
|
deba@2211
|
355 |
}
|
deba@2211
|
356 |
if (!_current_arc) {
|
deba@2211
|
357 |
_current_arc = new CurrentArcMap(*_graph);
|
deba@2211
|
358 |
}
|
deba@2211
|
359 |
if (!_min_cut_map) {
|
deba@2211
|
360 |
_min_cut_map = new MinCutMap(*_graph);
|
deba@2211
|
361 |
}
|
deba@2211
|
362 |
if (!_res_graph) {
|
deba@2211
|
363 |
_res_graph = new ResGraph(*_graph, *_capacity, *_preflow);
|
deba@2211
|
364 |
}
|
deba@2211
|
365 |
|
deba@2211
|
366 |
_min_cut = std::numeric_limits<Value>::max();
|
deba@2211
|
367 |
}
|
deba@2211
|
368 |
|
deba@2211
|
369 |
|
deba@2211
|
370 |
/// \brief Calculates the minimum cut with the \c source node
|
deba@2211
|
371 |
/// in the first partition.
|
deba@2211
|
372 |
///
|
deba@2211
|
373 |
/// Calculates the minimum cut with the \c source node
|
deba@2211
|
374 |
/// in the first partition.
|
deba@2211
|
375 |
void calculateOut() {
|
deba@2211
|
376 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
377 |
if (it != _source) {
|
deba@2211
|
378 |
calculateOut(it);
|
deba@2211
|
379 |
return;
|
deba@2211
|
380 |
}
|
deba@2211
|
381 |
}
|
deba@2211
|
382 |
}
|
deba@2211
|
383 |
|
deba@2211
|
384 |
/// \brief Calculates the minimum cut with the \c source node
|
deba@2211
|
385 |
/// in the first partition.
|
deba@2211
|
386 |
///
|
deba@2211
|
387 |
/// Calculates the minimum cut with the \c source node
|
deba@2211
|
388 |
/// in the first partition. The \c target is the initial target
|
deba@2211
|
389 |
/// for the push-relabel algorithm.
|
deba@2211
|
390 |
void calculateOut(const Node& target) {
|
deba@2211
|
391 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
392 |
(*_wake)[it] = true;
|
deba@2211
|
393 |
(*_dist)[it] = 1;
|
deba@2211
|
394 |
(*_excess)[it] = 0;
|
deba@2211
|
395 |
(*_source_set)[it] = false;
|
deba@2211
|
396 |
|
deba@2211
|
397 |
_res_graph->firstOut((*_current_arc)[it], it);
|
deba@2211
|
398 |
}
|
deba@2211
|
399 |
|
deba@2211
|
400 |
_target = target;
|
deba@2211
|
401 |
(*_dist)[target] = 0;
|
deba@2211
|
402 |
|
deba@2211
|
403 |
for (ResOutEdgeIt it(*_res_graph, _source); it != INVALID; ++it) {
|
deba@2211
|
404 |
push(it, _res_graph->rescap(it));
|
deba@2211
|
405 |
}
|
deba@2211
|
406 |
|
deba@2211
|
407 |
_dormant[0].push_front(_source);
|
deba@2211
|
408 |
(*_source_set)[_source] = true;
|
deba@2211
|
409 |
_dormant_max = 0;
|
deba@2211
|
410 |
(*_wake)[_source]=false;
|
deba@2211
|
411 |
|
deba@2211
|
412 |
_level_size[0] = 1;
|
deba@2211
|
413 |
_level_size[1] = _node_num - 1;
|
deba@2211
|
414 |
|
deba@2211
|
415 |
do {
|
deba@2211
|
416 |
Node n;
|
deba@2211
|
417 |
while ((n = findActiveNode()) != INVALID) {
|
deba@2211
|
418 |
ResEdge e;
|
deba@2211
|
419 |
while (_tolerance.positive((*_excess)[n]) &&
|
deba@2211
|
420 |
(e = findAdmissibleEdge(n)) != INVALID){
|
deba@2211
|
421 |
Value delta;
|
deba@2211
|
422 |
if ((*_excess)[n] < _res_graph->rescap(e)) {
|
deba@2211
|
423 |
delta = (*_excess)[n];
|
deba@2211
|
424 |
} else {
|
deba@2211
|
425 |
delta = _res_graph->rescap(e);
|
deba@2211
|
426 |
_res_graph->nextOut((*_current_arc)[n]);
|
deba@2211
|
427 |
}
|
deba@2211
|
428 |
if (!_tolerance.positive(delta)) continue;
|
deba@2211
|
429 |
_res_graph->augment(e, delta);
|
deba@2211
|
430 |
(*_excess)[_res_graph->source(e)] -= delta;
|
deba@2211
|
431 |
Node a = _res_graph->target(e);
|
deba@2211
|
432 |
if (!_tolerance.positive((*_excess)[a]) && a != _target) {
|
deba@2211
|
433 |
_active_nodes[(*_dist)[a]].push_front(a);
|
deba@2211
|
434 |
}
|
deba@2211
|
435 |
(*_excess)[a] += delta;
|
deba@2211
|
436 |
}
|
deba@2211
|
437 |
if (_tolerance.positive((*_excess)[n])) {
|
deba@2211
|
438 |
relabel(n);
|
deba@2211
|
439 |
}
|
deba@2211
|
440 |
}
|
deba@2211
|
441 |
|
deba@2211
|
442 |
Value current_value = cutValue();
|
deba@2211
|
443 |
if (_min_cut > current_value){
|
deba@2211
|
444 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
445 |
_min_cut_map->set(it, !(*_wake)[it]);
|
deba@2211
|
446 |
}
|
deba@2211
|
447 |
|
deba@2211
|
448 |
_min_cut = current_value;
|
deba@2211
|
449 |
}
|
deba@2211
|
450 |
|
deba@2211
|
451 |
} while (selectNewSink());
|
deba@2211
|
452 |
}
|
deba@2211
|
453 |
|
deba@2211
|
454 |
void calculateIn() {
|
deba@2211
|
455 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
456 |
if (it != _source) {
|
deba@2211
|
457 |
calculateIn(it);
|
deba@2211
|
458 |
return;
|
deba@2211
|
459 |
}
|
deba@2211
|
460 |
}
|
deba@2211
|
461 |
}
|
deba@2211
|
462 |
|
deba@2211
|
463 |
void run() {
|
deba@2211
|
464 |
init();
|
deba@2211
|
465 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
466 |
if (it != _source) {
|
deba@2211
|
467 |
startOut(it);
|
deba@2211
|
468 |
// startIn(it);
|
deba@2211
|
469 |
return;
|
deba@2211
|
470 |
}
|
deba@2211
|
471 |
}
|
deba@2211
|
472 |
}
|
deba@2211
|
473 |
|
deba@2211
|
474 |
void run(const Node& s) {
|
deba@2211
|
475 |
init(s);
|
deba@2211
|
476 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
477 |
if (it != _source) {
|
deba@2211
|
478 |
startOut(it);
|
deba@2211
|
479 |
// startIn(it);
|
deba@2211
|
480 |
return;
|
deba@2211
|
481 |
}
|
deba@2211
|
482 |
}
|
deba@2211
|
483 |
}
|
deba@2211
|
484 |
|
deba@2211
|
485 |
void run(const Node& s, const Node& t) {
|
deba@2211
|
486 |
init(s);
|
deba@2211
|
487 |
startOut(t);
|
deba@2211
|
488 |
startIn(t);
|
deba@2211
|
489 |
}
|
deba@2211
|
490 |
|
deba@2211
|
491 |
/// \brief Returns the value of the minimum value cut with node \c
|
deba@2211
|
492 |
/// source on the source side.
|
deba@2211
|
493 |
///
|
deba@2211
|
494 |
/// Returns the value of the minimum value cut with node \c source
|
deba@2211
|
495 |
/// on the source side. This function can be called after running
|
deba@2211
|
496 |
/// \ref findMinCut.
|
deba@2211
|
497 |
Value minCut() const {
|
deba@2211
|
498 |
return _min_cut;
|
deba@2211
|
499 |
}
|
deba@2211
|
500 |
|
deba@2211
|
501 |
|
deba@2211
|
502 |
/// \brief Returns a minimum value cut.
|
deba@2211
|
503 |
///
|
deba@2211
|
504 |
/// Sets \c nodeMap to the characteristic vector of a minimum
|
deba@2211
|
505 |
/// value cut with node \c source on the source side. This
|
deba@2211
|
506 |
/// function can be called after running \ref findMinCut.
|
deba@2211
|
507 |
/// \pre nodeMap should be a bool-valued node-map.
|
deba@2211
|
508 |
template <typename NodeMap>
|
deba@2211
|
509 |
Value minCut(NodeMap& nodeMap) const {
|
deba@2211
|
510 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
511 |
nodeMap.set(it, (*_min_cut_map)[it]);
|
deba@2211
|
512 |
}
|
deba@2211
|
513 |
return minCut();
|
deba@2211
|
514 |
}
|
deba@2211
|
515 |
|
deba@2211
|
516 |
}; //class HaoOrlin
|
deba@2211
|
517 |
|
deba@2211
|
518 |
|
deba@2211
|
519 |
} //namespace lemon
|
deba@2211
|
520 |
|
deba@2211
|
521 |
#endif //LEMON_HAO_ORLIN_H
|