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