lemon/hao_orlin.h
author kpeter
Thu, 13 Nov 2008 16:17:50 +0000
changeset 2630 d239741cfd44
parent 2553 bfced05fa852
permissions -rw-r--r--
Various improvements in NetworkSimplex.

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