lemon/hao_orlin.h
author deba
Fri, 29 Sep 2006 11:23:54 +0000
changeset 2222 a24939ee343c
child 2225 bb3d5e6f9fcb
permissions -rw-r--r--
findEdge extension also for the BpUGraphs
proper handling of loop edges in the UGraph::findUEdge
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