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