lemon/preflow.h
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 982 bb70ad62c95f
parent 735 1f08e846df29
child 985 f63fd24c0aea
child 1027 30d5f950aa5f
permissions -rw-r--r--
Fix critical bug in preflow (#372)

The wrong transition between the bound decrease and highest active
heuristics caused the bug. The last node chosen in bound decrease mode
is used in the first iteration in highest active mode.
alpar@404
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@404
     2
 *
alpar@404
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@404
     4
 *
alpar@463
     5
 * Copyright (C) 2003-2009
alpar@404
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@404
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@404
     8
 *
alpar@404
     9
 * Permission to use, modify and distribute this software is granted
alpar@404
    10
 * provided that this copyright notice appears in all copies. For
alpar@404
    11
 * precise terms see the accompanying LICENSE file.
alpar@404
    12
 *
alpar@404
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@404
    14
 * express or implied, and with no claim as to its suitability for any
alpar@404
    15
 * purpose.
alpar@404
    16
 *
alpar@404
    17
 */
alpar@404
    18
alpar@404
    19
#ifndef LEMON_PREFLOW_H
alpar@404
    20
#define LEMON_PREFLOW_H
alpar@404
    21
alpar@404
    22
#include <lemon/tolerance.h>
alpar@404
    23
#include <lemon/elevator.h>
alpar@404
    24
alpar@404
    25
/// \file
alpar@404
    26
/// \ingroup max_flow
alpar@404
    27
/// \brief Implementation of the preflow algorithm.
alpar@404
    28
alpar@404
    29
namespace lemon {
alpar@404
    30
alpar@404
    31
  /// \brief Default traits class of Preflow class.
alpar@404
    32
  ///
alpar@404
    33
  /// Default traits class of Preflow class.
kpeter@525
    34
  /// \tparam GR Digraph type.
kpeter@606
    35
  /// \tparam CAP Capacity map type.
kpeter@606
    36
  template <typename GR, typename CAP>
alpar@404
    37
  struct PreflowDefaultTraits {
alpar@404
    38
kpeter@408
    39
    /// \brief The type of the digraph the algorithm runs on.
kpeter@525
    40
    typedef GR Digraph;
alpar@404
    41
alpar@404
    42
    /// \brief The type of the map that stores the arc capacities.
alpar@404
    43
    ///
alpar@404
    44
    /// The type of the map that stores the arc capacities.
alpar@404
    45
    /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
kpeter@606
    46
    typedef CAP CapacityMap;
alpar@404
    47
kpeter@408
    48
    /// \brief The type of the flow values.
kpeter@688
    49
    typedef typename CapacityMap::Value Value;
alpar@404
    50
kpeter@408
    51
    /// \brief The type of the map that stores the flow values.
alpar@404
    52
    ///
kpeter@408
    53
    /// The type of the map that stores the flow values.
alpar@404
    54
    /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
kpeter@688
    55
    typedef typename Digraph::template ArcMap<Value> FlowMap;
alpar@404
    56
alpar@404
    57
    /// \brief Instantiates a FlowMap.
alpar@404
    58
    ///
alpar@404
    59
    /// This function instantiates a \ref FlowMap.
kpeter@657
    60
    /// \param digraph The digraph for which we would like to define
alpar@404
    61
    /// the flow map.
alpar@404
    62
    static FlowMap* createFlowMap(const Digraph& digraph) {
alpar@404
    63
      return new FlowMap(digraph);
alpar@404
    64
    }
alpar@404
    65
kpeter@408
    66
    /// \brief The elevator type used by Preflow algorithm.
alpar@404
    67
    ///
alpar@404
    68
    /// The elevator type used by Preflow algorithm.
alpar@404
    69
    ///
alpar@404
    70
    /// \sa Elevator
alpar@404
    71
    /// \sa LinkedElevator
alpar@404
    72
    typedef LinkedElevator<Digraph, typename Digraph::Node> Elevator;
alpar@404
    73
alpar@404
    74
    /// \brief Instantiates an Elevator.
alpar@404
    75
    ///
kpeter@408
    76
    /// This function instantiates an \ref Elevator.
kpeter@657
    77
    /// \param digraph The digraph for which we would like to define
alpar@404
    78
    /// the elevator.
alpar@404
    79
    /// \param max_level The maximum level of the elevator.
alpar@404
    80
    static Elevator* createElevator(const Digraph& digraph, int max_level) {
alpar@404
    81
      return new Elevator(digraph, max_level);
alpar@404
    82
    }
alpar@404
    83
alpar@404
    84
    /// \brief The tolerance used by the algorithm
alpar@404
    85
    ///
alpar@404
    86
    /// The tolerance used by the algorithm to handle inexact computation.
kpeter@688
    87
    typedef lemon::Tolerance<Value> Tolerance;
alpar@404
    88
alpar@404
    89
  };
alpar@404
    90
alpar@404
    91
alpar@404
    92
  /// \ingroup max_flow
alpar@404
    93
  ///
kpeter@408
    94
  /// \brief %Preflow algorithm class.
alpar@404
    95
  ///
kpeter@408
    96
  /// This class provides an implementation of Goldberg-Tarjan's \e preflow
kpeter@606
    97
  /// \e push-relabel algorithm producing a \ref max_flow
kpeter@606
    98
  /// "flow of maximum value" in a digraph.
kpeter@606
    99
  /// The preflow algorithms are the fastest known maximum
alpar@404
   100
  /// flow algorithms. The current implementation use a mixture of the
alpar@404
   101
  /// \e "highest label" and the \e "bound decrease" heuristics.
alpar@404
   102
  /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{e})\f$.
alpar@404
   103
  ///
kpeter@408
   104
  /// The algorithm consists of two phases. After the first phase
kpeter@408
   105
  /// the maximum flow value and the minimum cut is obtained. The
kpeter@408
   106
  /// second phase constructs a feasible maximum flow on each arc.
alpar@404
   107
  ///
kpeter@525
   108
  /// \tparam GR The type of the digraph the algorithm runs on.
kpeter@606
   109
  /// \tparam CAP The type of the capacity map. The default map
kpeter@525
   110
  /// type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
alpar@404
   111
#ifdef DOXYGEN
kpeter@606
   112
  template <typename GR, typename CAP, typename TR>
alpar@404
   113
#else
kpeter@525
   114
  template <typename GR,
kpeter@606
   115
            typename CAP = typename GR::template ArcMap<int>,
kpeter@606
   116
            typename TR = PreflowDefaultTraits<GR, CAP> >
alpar@404
   117
#endif
alpar@404
   118
  class Preflow {
alpar@404
   119
  public:
alpar@404
   120
kpeter@408
   121
    ///The \ref PreflowDefaultTraits "traits class" of the algorithm.
kpeter@525
   122
    typedef TR Traits;
kpeter@408
   123
    ///The type of the digraph the algorithm runs on.
alpar@404
   124
    typedef typename Traits::Digraph Digraph;
kpeter@408
   125
    ///The type of the capacity map.
alpar@404
   126
    typedef typename Traits::CapacityMap CapacityMap;
kpeter@408
   127
    ///The type of the flow values.
kpeter@688
   128
    typedef typename Traits::Value Value;
alpar@404
   129
kpeter@408
   130
    ///The type of the flow map.
alpar@404
   131
    typedef typename Traits::FlowMap FlowMap;
kpeter@408
   132
    ///The type of the elevator.
alpar@404
   133
    typedef typename Traits::Elevator Elevator;
kpeter@408
   134
    ///The type of the tolerance.
alpar@404
   135
    typedef typename Traits::Tolerance Tolerance;
alpar@404
   136
alpar@404
   137
  private:
alpar@404
   138
alpar@404
   139
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
alpar@404
   140
alpar@404
   141
    const Digraph& _graph;
alpar@404
   142
    const CapacityMap* _capacity;
alpar@404
   143
alpar@404
   144
    int _node_num;
alpar@404
   145
alpar@404
   146
    Node _source, _target;
alpar@404
   147
alpar@404
   148
    FlowMap* _flow;
alpar@404
   149
    bool _local_flow;
alpar@404
   150
alpar@404
   151
    Elevator* _level;
alpar@404
   152
    bool _local_level;
alpar@404
   153
kpeter@688
   154
    typedef typename Digraph::template NodeMap<Value> ExcessMap;
alpar@404
   155
    ExcessMap* _excess;
alpar@404
   156
alpar@404
   157
    Tolerance _tolerance;
alpar@404
   158
alpar@404
   159
    bool _phase;
alpar@404
   160
alpar@404
   161
alpar@404
   162
    void createStructures() {
alpar@404
   163
      _node_num = countNodes(_graph);
alpar@404
   164
alpar@404
   165
      if (!_flow) {
alpar@404
   166
        _flow = Traits::createFlowMap(_graph);
alpar@404
   167
        _local_flow = true;
alpar@404
   168
      }
alpar@404
   169
      if (!_level) {
alpar@404
   170
        _level = Traits::createElevator(_graph, _node_num);
alpar@404
   171
        _local_level = true;
alpar@404
   172
      }
alpar@404
   173
      if (!_excess) {
alpar@404
   174
        _excess = new ExcessMap(_graph);
alpar@404
   175
      }
alpar@404
   176
    }
alpar@404
   177
alpar@404
   178
    void destroyStructures() {
alpar@404
   179
      if (_local_flow) {
alpar@404
   180
        delete _flow;
alpar@404
   181
      }
alpar@404
   182
      if (_local_level) {
alpar@404
   183
        delete _level;
alpar@404
   184
      }
alpar@404
   185
      if (_excess) {
alpar@404
   186
        delete _excess;
alpar@404
   187
      }
alpar@404
   188
    }
alpar@404
   189
alpar@404
   190
  public:
alpar@404
   191
alpar@404
   192
    typedef Preflow Create;
alpar@404
   193
kpeter@408
   194
    ///\name Named Template Parameters
alpar@404
   195
alpar@404
   196
    ///@{
alpar@404
   197
kpeter@606
   198
    template <typename T>
alpar@406
   199
    struct SetFlowMapTraits : public Traits {
kpeter@606
   200
      typedef T FlowMap;
alpar@404
   201
      static FlowMap *createFlowMap(const Digraph&) {
alpar@405
   202
        LEMON_ASSERT(false, "FlowMap is not initialized");
alpar@405
   203
        return 0; // ignore warnings
alpar@404
   204
      }
alpar@404
   205
    };
alpar@404
   206
alpar@404
   207
    /// \brief \ref named-templ-param "Named parameter" for setting
alpar@404
   208
    /// FlowMap type
alpar@404
   209
    ///
alpar@404
   210
    /// \ref named-templ-param "Named parameter" for setting FlowMap
kpeter@408
   211
    /// type.
kpeter@606
   212
    template <typename T>
alpar@406
   213
    struct SetFlowMap
kpeter@606
   214
      : public Preflow<Digraph, CapacityMap, SetFlowMapTraits<T> > {
alpar@404
   215
      typedef Preflow<Digraph, CapacityMap,
kpeter@606
   216
                      SetFlowMapTraits<T> > Create;
alpar@404
   217
    };
alpar@404
   218
kpeter@606
   219
    template <typename T>
alpar@406
   220
    struct SetElevatorTraits : public Traits {
kpeter@606
   221
      typedef T Elevator;
alpar@404
   222
      static Elevator *createElevator(const Digraph&, int) {
alpar@405
   223
        LEMON_ASSERT(false, "Elevator is not initialized");
alpar@405
   224
        return 0; // ignore warnings
alpar@404
   225
      }
alpar@404
   226
    };
alpar@404
   227
alpar@404
   228
    /// \brief \ref named-templ-param "Named parameter" for setting
alpar@404
   229
    /// Elevator type
alpar@404
   230
    ///
alpar@404
   231
    /// \ref named-templ-param "Named parameter" for setting Elevator
kpeter@408
   232
    /// type. If this named parameter is used, then an external
kpeter@408
   233
    /// elevator object must be passed to the algorithm using the
kpeter@408
   234
    /// \ref elevator(Elevator&) "elevator()" function before calling
kpeter@408
   235
    /// \ref run() or \ref init().
kpeter@408
   236
    /// \sa SetStandardElevator
kpeter@606
   237
    template <typename T>
alpar@406
   238
    struct SetElevator
kpeter@606
   239
      : public Preflow<Digraph, CapacityMap, SetElevatorTraits<T> > {
alpar@404
   240
      typedef Preflow<Digraph, CapacityMap,
kpeter@606
   241
                      SetElevatorTraits<T> > Create;
alpar@404
   242
    };
alpar@404
   243
kpeter@606
   244
    template <typename T>
alpar@406
   245
    struct SetStandardElevatorTraits : public Traits {
kpeter@606
   246
      typedef T Elevator;
alpar@404
   247
      static Elevator *createElevator(const Digraph& digraph, int max_level) {
alpar@404
   248
        return new Elevator(digraph, max_level);
alpar@404
   249
      }
alpar@404
   250
    };
alpar@404
   251
alpar@404
   252
    /// \brief \ref named-templ-param "Named parameter" for setting
kpeter@408
   253
    /// Elevator type with automatic allocation
alpar@404
   254
    ///
alpar@404
   255
    /// \ref named-templ-param "Named parameter" for setting Elevator
kpeter@408
   256
    /// type with automatic allocation.
kpeter@408
   257
    /// The Elevator should have standard constructor interface to be
kpeter@408
   258
    /// able to automatically created by the algorithm (i.e. the
kpeter@408
   259
    /// digraph and the maximum level should be passed to it).
kpeter@408
   260
    /// However an external elevator object could also be passed to the
kpeter@408
   261
    /// algorithm with the \ref elevator(Elevator&) "elevator()" function
kpeter@408
   262
    /// before calling \ref run() or \ref init().
kpeter@408
   263
    /// \sa SetElevator
kpeter@606
   264
    template <typename T>
alpar@406
   265
    struct SetStandardElevator
alpar@404
   266
      : public Preflow<Digraph, CapacityMap,
kpeter@606
   267
                       SetStandardElevatorTraits<T> > {
alpar@404
   268
      typedef Preflow<Digraph, CapacityMap,
kpeter@606
   269
                      SetStandardElevatorTraits<T> > Create;
alpar@404
   270
    };
alpar@404
   271
alpar@404
   272
    /// @}
alpar@404
   273
alpar@404
   274
  protected:
alpar@404
   275
alpar@404
   276
    Preflow() {}
alpar@404
   277
alpar@404
   278
  public:
alpar@404
   279
alpar@404
   280
alpar@404
   281
    /// \brief The constructor of the class.
alpar@404
   282
    ///
alpar@404
   283
    /// The constructor of the class.
alpar@404
   284
    /// \param digraph The digraph the algorithm runs on.
alpar@404
   285
    /// \param capacity The capacity of the arcs.
alpar@404
   286
    /// \param source The source node.
alpar@404
   287
    /// \param target The target node.
alpar@404
   288
    Preflow(const Digraph& digraph, const CapacityMap& capacity,
kpeter@408
   289
            Node source, Node target)
alpar@404
   290
      : _graph(digraph), _capacity(&capacity),
alpar@404
   291
        _node_num(0), _source(source), _target(target),
alpar@404
   292
        _flow(0), _local_flow(false),
alpar@404
   293
        _level(0), _local_level(false),
alpar@404
   294
        _excess(0), _tolerance(), _phase() {}
alpar@404
   295
kpeter@408
   296
    /// \brief Destructor.
alpar@404
   297
    ///
alpar@404
   298
    /// Destructor.
alpar@404
   299
    ~Preflow() {
alpar@404
   300
      destroyStructures();
alpar@404
   301
    }
alpar@404
   302
alpar@404
   303
    /// \brief Sets the capacity map.
alpar@404
   304
    ///
alpar@404
   305
    /// Sets the capacity map.
kpeter@408
   306
    /// \return <tt>(*this)</tt>
alpar@404
   307
    Preflow& capacityMap(const CapacityMap& map) {
alpar@404
   308
      _capacity = &map;
alpar@404
   309
      return *this;
alpar@404
   310
    }
alpar@404
   311
alpar@404
   312
    /// \brief Sets the flow map.
alpar@404
   313
    ///
alpar@404
   314
    /// Sets the flow map.
kpeter@408
   315
    /// If you don't use this function before calling \ref run() or
kpeter@408
   316
    /// \ref init(), an instance will be allocated automatically.
kpeter@408
   317
    /// The destructor deallocates this automatically allocated map,
kpeter@408
   318
    /// of course.
kpeter@408
   319
    /// \return <tt>(*this)</tt>
alpar@404
   320
    Preflow& flowMap(FlowMap& map) {
alpar@404
   321
      if (_local_flow) {
alpar@404
   322
        delete _flow;
alpar@404
   323
        _local_flow = false;
alpar@404
   324
      }
alpar@404
   325
      _flow = &map;
alpar@404
   326
      return *this;
alpar@404
   327
    }
alpar@404
   328
kpeter@408
   329
    /// \brief Sets the source node.
alpar@404
   330
    ///
kpeter@408
   331
    /// Sets the source node.
kpeter@408
   332
    /// \return <tt>(*this)</tt>
kpeter@408
   333
    Preflow& source(const Node& node) {
kpeter@408
   334
      _source = node;
kpeter@408
   335
      return *this;
alpar@404
   336
    }
alpar@404
   337
kpeter@408
   338
    /// \brief Sets the target node.
alpar@404
   339
    ///
kpeter@408
   340
    /// Sets the target node.
kpeter@408
   341
    /// \return <tt>(*this)</tt>
kpeter@408
   342
    Preflow& target(const Node& node) {
kpeter@408
   343
      _target = node;
kpeter@408
   344
      return *this;
kpeter@408
   345
    }
kpeter@408
   346
kpeter@408
   347
    /// \brief Sets the elevator used by algorithm.
kpeter@408
   348
    ///
kpeter@408
   349
    /// Sets the elevator used by algorithm.
kpeter@408
   350
    /// If you don't use this function before calling \ref run() or
kpeter@408
   351
    /// \ref init(), an instance will be allocated automatically.
kpeter@408
   352
    /// The destructor deallocates this automatically allocated elevator,
kpeter@408
   353
    /// of course.
kpeter@408
   354
    /// \return <tt>(*this)</tt>
alpar@404
   355
    Preflow& elevator(Elevator& elevator) {
alpar@404
   356
      if (_local_level) {
alpar@404
   357
        delete _level;
alpar@404
   358
        _local_level = false;
alpar@404
   359
      }
alpar@404
   360
      _level = &elevator;
alpar@404
   361
      return *this;
alpar@404
   362
    }
alpar@404
   363
kpeter@408
   364
    /// \brief Returns a const reference to the elevator.
alpar@404
   365
    ///
kpeter@408
   366
    /// Returns a const reference to the elevator.
kpeter@408
   367
    ///
kpeter@408
   368
    /// \pre Either \ref run() or \ref init() must be called before
kpeter@408
   369
    /// using this function.
kpeter@437
   370
    const Elevator& elevator() const {
alpar@404
   371
      return *_level;
alpar@404
   372
    }
alpar@404
   373
alpar@404
   374
    /// \brief Sets the tolerance used by algorithm.
alpar@404
   375
    ///
alpar@404
   376
    /// Sets the tolerance used by algorithm.
kpeter@735
   377
    Preflow& tolerance(const Tolerance& tolerance) {
alpar@404
   378
      _tolerance = tolerance;
alpar@404
   379
      return *this;
alpar@404
   380
    }
alpar@404
   381
kpeter@408
   382
    /// \brief Returns a const reference to the tolerance.
alpar@404
   383
    ///
kpeter@408
   384
    /// Returns a const reference to the tolerance.
alpar@404
   385
    const Tolerance& tolerance() const {
kpeter@735
   386
      return _tolerance;
alpar@404
   387
    }
alpar@404
   388
kpeter@408
   389
    /// \name Execution Control
kpeter@408
   390
    /// The simplest way to execute the preflow algorithm is to use
kpeter@408
   391
    /// \ref run() or \ref runMinCut().\n
kpeter@408
   392
    /// If you need more control on the initial solution or the execution,
kpeter@408
   393
    /// first you have to call one of the \ref init() functions, then
kpeter@408
   394
    /// \ref startFirstPhase() and if you need it \ref startSecondPhase().
alpar@404
   395
alpar@404
   396
    ///@{
alpar@404
   397
alpar@404
   398
    /// \brief Initializes the internal data structures.
alpar@404
   399
    ///
kpeter@408
   400
    /// Initializes the internal data structures and sets the initial
kpeter@408
   401
    /// flow to zero on each arc.
alpar@404
   402
    void init() {
alpar@404
   403
      createStructures();
alpar@404
   404
alpar@404
   405
      _phase = true;
alpar@404
   406
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@628
   407
        (*_excess)[n] = 0;
alpar@404
   408
      }
alpar@404
   409
alpar@404
   410
      for (ArcIt e(_graph); e != INVALID; ++e) {
alpar@404
   411
        _flow->set(e, 0);
alpar@404
   412
      }
alpar@404
   413
alpar@404
   414
      typename Digraph::template NodeMap<bool> reached(_graph, false);
alpar@404
   415
alpar@404
   416
      _level->initStart();
alpar@404
   417
      _level->initAddItem(_target);
alpar@404
   418
alpar@404
   419
      std::vector<Node> queue;
kpeter@628
   420
      reached[_source] = true;
alpar@404
   421
alpar@404
   422
      queue.push_back(_target);
kpeter@628
   423
      reached[_target] = true;
alpar@404
   424
      while (!queue.empty()) {
alpar@404
   425
        _level->initNewLevel();
alpar@404
   426
        std::vector<Node> nqueue;
alpar@404
   427
        for (int i = 0; i < int(queue.size()); ++i) {
alpar@404
   428
          Node n = queue[i];
alpar@404
   429
          for (InArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   430
            Node u = _graph.source(e);
alpar@404
   431
            if (!reached[u] && _tolerance.positive((*_capacity)[e])) {
kpeter@628
   432
              reached[u] = true;
alpar@404
   433
              _level->initAddItem(u);
alpar@404
   434
              nqueue.push_back(u);
alpar@404
   435
            }
alpar@404
   436
          }
alpar@404
   437
        }
alpar@404
   438
        queue.swap(nqueue);
alpar@404
   439
      }
alpar@404
   440
      _level->initFinish();
alpar@404
   441
alpar@404
   442
      for (OutArcIt e(_graph, _source); e != INVALID; ++e) {
alpar@404
   443
        if (_tolerance.positive((*_capacity)[e])) {
alpar@404
   444
          Node u = _graph.target(e);
alpar@404
   445
          if ((*_level)[u] == _level->maxLevel()) continue;
alpar@404
   446
          _flow->set(e, (*_capacity)[e]);
kpeter@628
   447
          (*_excess)[u] += (*_capacity)[e];
alpar@404
   448
          if (u != _target && !_level->active(u)) {
alpar@404
   449
            _level->activate(u);
alpar@404
   450
          }
alpar@404
   451
        }
alpar@404
   452
      }
alpar@404
   453
    }
alpar@404
   454
kpeter@408
   455
    /// \brief Initializes the internal data structures using the
kpeter@408
   456
    /// given flow map.
alpar@404
   457
    ///
alpar@404
   458
    /// Initializes the internal data structures and sets the initial
alpar@404
   459
    /// flow to the given \c flowMap. The \c flowMap should contain a
kpeter@408
   460
    /// flow or at least a preflow, i.e. at each node excluding the
kpeter@408
   461
    /// source node the incoming flow should greater or equal to the
alpar@404
   462
    /// outgoing flow.
kpeter@408
   463
    /// \return \c false if the given \c flowMap is not a preflow.
alpar@404
   464
    template <typename FlowMap>
kpeter@407
   465
    bool init(const FlowMap& flowMap) {
alpar@404
   466
      createStructures();
alpar@404
   467
alpar@404
   468
      for (ArcIt e(_graph); e != INVALID; ++e) {
alpar@404
   469
        _flow->set(e, flowMap[e]);
alpar@404
   470
      }
alpar@404
   471
alpar@404
   472
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@688
   473
        Value excess = 0;
alpar@404
   474
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   475
          excess += (*_flow)[e];
alpar@404
   476
        }
alpar@404
   477
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   478
          excess -= (*_flow)[e];
alpar@404
   479
        }
alpar@404
   480
        if (excess < 0 && n != _source) return false;
kpeter@628
   481
        (*_excess)[n] = excess;
alpar@404
   482
      }
alpar@404
   483
alpar@404
   484
      typename Digraph::template NodeMap<bool> reached(_graph, false);
alpar@404
   485
alpar@404
   486
      _level->initStart();
alpar@404
   487
      _level->initAddItem(_target);
alpar@404
   488
alpar@404
   489
      std::vector<Node> queue;
kpeter@628
   490
      reached[_source] = true;
alpar@404
   491
alpar@404
   492
      queue.push_back(_target);
kpeter@628
   493
      reached[_target] = true;
alpar@404
   494
      while (!queue.empty()) {
alpar@404
   495
        _level->initNewLevel();
alpar@404
   496
        std::vector<Node> nqueue;
alpar@404
   497
        for (int i = 0; i < int(queue.size()); ++i) {
alpar@404
   498
          Node n = queue[i];
alpar@404
   499
          for (InArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   500
            Node u = _graph.source(e);
alpar@404
   501
            if (!reached[u] &&
alpar@404
   502
                _tolerance.positive((*_capacity)[e] - (*_flow)[e])) {
kpeter@628
   503
              reached[u] = true;
alpar@404
   504
              _level->initAddItem(u);
alpar@404
   505
              nqueue.push_back(u);
alpar@404
   506
            }
alpar@404
   507
          }
alpar@404
   508
          for (OutArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   509
            Node v = _graph.target(e);
alpar@404
   510
            if (!reached[v] && _tolerance.positive((*_flow)[e])) {
kpeter@628
   511
              reached[v] = true;
alpar@404
   512
              _level->initAddItem(v);
alpar@404
   513
              nqueue.push_back(v);
alpar@404
   514
            }
alpar@404
   515
          }
alpar@404
   516
        }
alpar@404
   517
        queue.swap(nqueue);
alpar@404
   518
      }
alpar@404
   519
      _level->initFinish();
alpar@404
   520
alpar@404
   521
      for (OutArcIt e(_graph, _source); e != INVALID; ++e) {
kpeter@688
   522
        Value rem = (*_capacity)[e] - (*_flow)[e];
alpar@404
   523
        if (_tolerance.positive(rem)) {
alpar@404
   524
          Node u = _graph.target(e);
alpar@404
   525
          if ((*_level)[u] == _level->maxLevel()) continue;
alpar@404
   526
          _flow->set(e, (*_capacity)[e]);
kpeter@628
   527
          (*_excess)[u] += rem;
alpar@404
   528
          if (u != _target && !_level->active(u)) {
alpar@404
   529
            _level->activate(u);
alpar@404
   530
          }
alpar@404
   531
        }
alpar@404
   532
      }
alpar@404
   533
      for (InArcIt e(_graph, _source); e != INVALID; ++e) {
kpeter@688
   534
        Value rem = (*_flow)[e];
alpar@404
   535
        if (_tolerance.positive(rem)) {
alpar@404
   536
          Node v = _graph.source(e);
alpar@404
   537
          if ((*_level)[v] == _level->maxLevel()) continue;
alpar@404
   538
          _flow->set(e, 0);
kpeter@628
   539
          (*_excess)[v] += rem;
alpar@404
   540
          if (v != _target && !_level->active(v)) {
alpar@404
   541
            _level->activate(v);
alpar@404
   542
          }
alpar@404
   543
        }
alpar@404
   544
      }
alpar@404
   545
      return true;
alpar@404
   546
    }
alpar@404
   547
alpar@404
   548
    /// \brief Starts the first phase of the preflow algorithm.
alpar@404
   549
    ///
alpar@404
   550
    /// The preflow algorithm consists of two phases, this method runs
alpar@404
   551
    /// the first phase. After the first phase the maximum flow value
alpar@404
   552
    /// and a minimum value cut can already be computed, although a
alpar@404
   553
    /// maximum flow is not yet obtained. So after calling this method
alpar@404
   554
    /// \ref flowValue() returns the value of a maximum flow and \ref
alpar@404
   555
    /// minCut() returns a minimum cut.
kpeter@408
   556
    /// \pre One of the \ref init() functions must be called before
kpeter@408
   557
    /// using this function.
alpar@404
   558
    void startFirstPhase() {
alpar@404
   559
      _phase = true;
alpar@404
   560
deba@982
   561
      while (true) {
alpar@404
   562
        int num = _node_num;
alpar@404
   563
deba@982
   564
        Node n = INVALID;
deba@982
   565
        int level = -1;
deba@982
   566
deba@982
   567
        while (num > 0) {
deba@982
   568
          n = _level->highestActive();
deba@982
   569
          if (n == INVALID) goto first_phase_done;
deba@982
   570
          level = _level->highestActiveLevel();
deba@982
   571
          --num;
deba@982
   572
          
kpeter@688
   573
          Value excess = (*_excess)[n];
alpar@404
   574
          int new_level = _level->maxLevel();
alpar@404
   575
alpar@404
   576
          for (OutArcIt e(_graph, n); e != INVALID; ++e) {
kpeter@688
   577
            Value rem = (*_capacity)[e] - (*_flow)[e];
alpar@404
   578
            if (!_tolerance.positive(rem)) continue;
alpar@404
   579
            Node v = _graph.target(e);
alpar@404
   580
            if ((*_level)[v] < level) {
alpar@404
   581
              if (!_level->active(v) && v != _target) {
alpar@404
   582
                _level->activate(v);
alpar@404
   583
              }
alpar@404
   584
              if (!_tolerance.less(rem, excess)) {
alpar@404
   585
                _flow->set(e, (*_flow)[e] + excess);
kpeter@628
   586
                (*_excess)[v] += excess;
alpar@404
   587
                excess = 0;
alpar@404
   588
                goto no_more_push_1;
alpar@404
   589
              } else {
alpar@404
   590
                excess -= rem;
kpeter@628
   591
                (*_excess)[v] += rem;
alpar@404
   592
                _flow->set(e, (*_capacity)[e]);
alpar@404
   593
              }
alpar@404
   594
            } else if (new_level > (*_level)[v]) {
alpar@404
   595
              new_level = (*_level)[v];
alpar@404
   596
            }
alpar@404
   597
          }
alpar@404
   598
alpar@404
   599
          for (InArcIt e(_graph, n); e != INVALID; ++e) {
kpeter@688
   600
            Value rem = (*_flow)[e];
alpar@404
   601
            if (!_tolerance.positive(rem)) continue;
alpar@404
   602
            Node v = _graph.source(e);
alpar@404
   603
            if ((*_level)[v] < level) {
alpar@404
   604
              if (!_level->active(v) && v != _target) {
alpar@404
   605
                _level->activate(v);
alpar@404
   606
              }
alpar@404
   607
              if (!_tolerance.less(rem, excess)) {
alpar@404
   608
                _flow->set(e, (*_flow)[e] - excess);
kpeter@628
   609
                (*_excess)[v] += excess;
alpar@404
   610
                excess = 0;
alpar@404
   611
                goto no_more_push_1;
alpar@404
   612
              } else {
alpar@404
   613
                excess -= rem;
kpeter@628
   614
                (*_excess)[v] += rem;
alpar@404
   615
                _flow->set(e, 0);
alpar@404
   616
              }
alpar@404
   617
            } else if (new_level > (*_level)[v]) {
alpar@404
   618
              new_level = (*_level)[v];
alpar@404
   619
            }
alpar@404
   620
          }
alpar@404
   621
alpar@404
   622
        no_more_push_1:
alpar@404
   623
kpeter@628
   624
          (*_excess)[n] = excess;
alpar@404
   625
alpar@404
   626
          if (excess != 0) {
alpar@404
   627
            if (new_level + 1 < _level->maxLevel()) {
alpar@404
   628
              _level->liftHighestActive(new_level + 1);
alpar@404
   629
            } else {
alpar@404
   630
              _level->liftHighestActiveToTop();
alpar@404
   631
            }
alpar@404
   632
            if (_level->emptyLevel(level)) {
alpar@404
   633
              _level->liftToTop(level);
alpar@404
   634
            }
alpar@404
   635
          } else {
alpar@404
   636
            _level->deactivate(n);
alpar@404
   637
          }
alpar@404
   638
        }
alpar@404
   639
alpar@404
   640
        num = _node_num * 20;
deba@982
   641
        while (num > 0) {
deba@982
   642
          while (level >= 0 && _level->activeFree(level)) {
deba@982
   643
            --level;
deba@982
   644
          }
deba@982
   645
          if (level == -1) {
deba@982
   646
            n = _level->highestActive();
deba@982
   647
            level = _level->highestActiveLevel();
deba@982
   648
            if (n == INVALID) goto first_phase_done;
deba@982
   649
          } else {
deba@982
   650
            n = _level->activeOn(level);
deba@982
   651
          }
deba@982
   652
          --num;
deba@982
   653
kpeter@688
   654
          Value excess = (*_excess)[n];
alpar@404
   655
          int new_level = _level->maxLevel();
alpar@404
   656
alpar@404
   657
          for (OutArcIt e(_graph, n); e != INVALID; ++e) {
kpeter@688
   658
            Value rem = (*_capacity)[e] - (*_flow)[e];
alpar@404
   659
            if (!_tolerance.positive(rem)) continue;
alpar@404
   660
            Node v = _graph.target(e);
alpar@404
   661
            if ((*_level)[v] < level) {
alpar@404
   662
              if (!_level->active(v) && v != _target) {
alpar@404
   663
                _level->activate(v);
alpar@404
   664
              }
alpar@404
   665
              if (!_tolerance.less(rem, excess)) {
alpar@404
   666
                _flow->set(e, (*_flow)[e] + excess);
kpeter@628
   667
                (*_excess)[v] += excess;
alpar@404
   668
                excess = 0;
alpar@404
   669
                goto no_more_push_2;
alpar@404
   670
              } else {
alpar@404
   671
                excess -= rem;
kpeter@628
   672
                (*_excess)[v] += rem;
alpar@404
   673
                _flow->set(e, (*_capacity)[e]);
alpar@404
   674
              }
alpar@404
   675
            } else if (new_level > (*_level)[v]) {
alpar@404
   676
              new_level = (*_level)[v];
alpar@404
   677
            }
alpar@404
   678
          }
alpar@404
   679
alpar@404
   680
          for (InArcIt e(_graph, n); e != INVALID; ++e) {
kpeter@688
   681
            Value rem = (*_flow)[e];
alpar@404
   682
            if (!_tolerance.positive(rem)) continue;
alpar@404
   683
            Node v = _graph.source(e);
alpar@404
   684
            if ((*_level)[v] < level) {
alpar@404
   685
              if (!_level->active(v) && v != _target) {
alpar@404
   686
                _level->activate(v);
alpar@404
   687
              }
alpar@404
   688
              if (!_tolerance.less(rem, excess)) {
alpar@404
   689
                _flow->set(e, (*_flow)[e] - excess);
kpeter@628
   690
                (*_excess)[v] += excess;
alpar@404
   691
                excess = 0;
alpar@404
   692
                goto no_more_push_2;
alpar@404
   693
              } else {
alpar@404
   694
                excess -= rem;
kpeter@628
   695
                (*_excess)[v] += rem;
alpar@404
   696
                _flow->set(e, 0);
alpar@404
   697
              }
alpar@404
   698
            } else if (new_level > (*_level)[v]) {
alpar@404
   699
              new_level = (*_level)[v];
alpar@404
   700
            }
alpar@404
   701
          }
alpar@404
   702
alpar@404
   703
        no_more_push_2:
alpar@404
   704
kpeter@628
   705
          (*_excess)[n] = excess;
alpar@404
   706
alpar@404
   707
          if (excess != 0) {
alpar@404
   708
            if (new_level + 1 < _level->maxLevel()) {
alpar@404
   709
              _level->liftActiveOn(level, new_level + 1);
alpar@404
   710
            } else {
alpar@404
   711
              _level->liftActiveToTop(level);
alpar@404
   712
            }
alpar@404
   713
            if (_level->emptyLevel(level)) {
alpar@404
   714
              _level->liftToTop(level);
alpar@404
   715
            }
alpar@404
   716
          } else {
alpar@404
   717
            _level->deactivate(n);
alpar@404
   718
          }
alpar@404
   719
        }
alpar@404
   720
      }
deba@982
   721
    first_phase_done:;
alpar@404
   722
    }
alpar@404
   723
alpar@404
   724
    /// \brief Starts the second phase of the preflow algorithm.
alpar@404
   725
    ///
alpar@404
   726
    /// The preflow algorithm consists of two phases, this method runs
kpeter@408
   727
    /// the second phase. After calling one of the \ref init() functions
kpeter@408
   728
    /// and \ref startFirstPhase() and then \ref startSecondPhase(),
kpeter@408
   729
    /// \ref flowMap() returns a maximum flow, \ref flowValue() returns the
alpar@404
   730
    /// value of a maximum flow, \ref minCut() returns a minimum cut
kpeter@408
   731
    /// \pre One of the \ref init() functions and \ref startFirstPhase()
kpeter@408
   732
    /// must be called before using this function.
alpar@404
   733
    void startSecondPhase() {
alpar@404
   734
      _phase = false;
alpar@404
   735
alpar@404
   736
      typename Digraph::template NodeMap<bool> reached(_graph);
alpar@404
   737
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@628
   738
        reached[n] = (*_level)[n] < _level->maxLevel();
alpar@404
   739
      }
alpar@404
   740
alpar@404
   741
      _level->initStart();
alpar@404
   742
      _level->initAddItem(_source);
alpar@404
   743
alpar@404
   744
      std::vector<Node> queue;
alpar@404
   745
      queue.push_back(_source);
kpeter@628
   746
      reached[_source] = true;
alpar@404
   747
alpar@404
   748
      while (!queue.empty()) {
alpar@404
   749
        _level->initNewLevel();
alpar@404
   750
        std::vector<Node> nqueue;
alpar@404
   751
        for (int i = 0; i < int(queue.size()); ++i) {
alpar@404
   752
          Node n = queue[i];
alpar@404
   753
          for (OutArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   754
            Node v = _graph.target(e);
alpar@404
   755
            if (!reached[v] && _tolerance.positive((*_flow)[e])) {
kpeter@628
   756
              reached[v] = true;
alpar@404
   757
              _level->initAddItem(v);
alpar@404
   758
              nqueue.push_back(v);
alpar@404
   759
            }
alpar@404
   760
          }
alpar@404
   761
          for (InArcIt e(_graph, n); e != INVALID; ++e) {
alpar@404
   762
            Node u = _graph.source(e);
alpar@404
   763
            if (!reached[u] &&
alpar@404
   764
                _tolerance.positive((*_capacity)[e] - (*_flow)[e])) {
kpeter@628
   765
              reached[u] = true;
alpar@404
   766
              _level->initAddItem(u);
alpar@404
   767
              nqueue.push_back(u);
alpar@404
   768
            }
alpar@404
   769
          }
alpar@404
   770
        }
alpar@404
   771
        queue.swap(nqueue);
alpar@404
   772
      }
alpar@404
   773
      _level->initFinish();
alpar@404
   774
alpar@404
   775
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@404
   776
        if (!reached[n]) {
alpar@404
   777
          _level->dirtyTopButOne(n);
alpar@404
   778
        } else if ((*_excess)[n] > 0 && _target != n) {
alpar@404
   779
          _level->activate(n);
alpar@404
   780
        }
alpar@404
   781
      }
alpar@404
   782
alpar@404
   783
      Node n;
alpar@404
   784
      while ((n = _level->highestActive()) != INVALID) {
kpeter@688
   785
        Value excess = (*_excess)[n];
alpar@404
   786
        int level = _level->highestActiveLevel();
alpar@404
   787
        int new_level = _level->maxLevel();
alpar@404
   788
alpar@404
   789
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
kpeter@688
   790
          Value rem = (*_capacity)[e] - (*_flow)[e];
alpar@404
   791
          if (!_tolerance.positive(rem)) continue;
alpar@404
   792
          Node v = _graph.target(e);
alpar@404
   793
          if ((*_level)[v] < level) {
alpar@404
   794
            if (!_level->active(v) && v != _source) {
alpar@404
   795
              _level->activate(v);
alpar@404
   796
            }
alpar@404
   797
            if (!_tolerance.less(rem, excess)) {
alpar@404
   798
              _flow->set(e, (*_flow)[e] + excess);
kpeter@628
   799
              (*_excess)[v] += excess;
alpar@404
   800
              excess = 0;
alpar@404
   801
              goto no_more_push;
alpar@404
   802
            } else {
alpar@404
   803
              excess -= rem;
kpeter@628
   804
              (*_excess)[v] += rem;
alpar@404
   805
              _flow->set(e, (*_capacity)[e]);
alpar@404
   806
            }
alpar@404
   807
          } else if (new_level > (*_level)[v]) {
alpar@404
   808
            new_level = (*_level)[v];
alpar@404
   809
          }
alpar@404
   810
        }
alpar@404
   811
alpar@404
   812
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
kpeter@688
   813
          Value rem = (*_flow)[e];
alpar@404
   814
          if (!_tolerance.positive(rem)) continue;
alpar@404
   815
          Node v = _graph.source(e);
alpar@404
   816
          if ((*_level)[v] < level) {
alpar@404
   817
            if (!_level->active(v) && v != _source) {
alpar@404
   818
              _level->activate(v);
alpar@404
   819
            }
alpar@404
   820
            if (!_tolerance.less(rem, excess)) {
alpar@404
   821
              _flow->set(e, (*_flow)[e] - excess);
kpeter@628
   822
              (*_excess)[v] += excess;
alpar@404
   823
              excess = 0;
alpar@404
   824
              goto no_more_push;
alpar@404
   825
            } else {
alpar@404
   826
              excess -= rem;
kpeter@628
   827
              (*_excess)[v] += rem;
alpar@404
   828
              _flow->set(e, 0);
alpar@404
   829
            }
alpar@404
   830
          } else if (new_level > (*_level)[v]) {
alpar@404
   831
            new_level = (*_level)[v];
alpar@404
   832
          }
alpar@404
   833
        }
alpar@404
   834
alpar@404
   835
      no_more_push:
alpar@404
   836
kpeter@628
   837
        (*_excess)[n] = excess;
alpar@404
   838
alpar@404
   839
        if (excess != 0) {
alpar@404
   840
          if (new_level + 1 < _level->maxLevel()) {
alpar@404
   841
            _level->liftHighestActive(new_level + 1);
alpar@404
   842
          } else {
alpar@404
   843
            // Calculation error
alpar@404
   844
            _level->liftHighestActiveToTop();
alpar@404
   845
          }
alpar@404
   846
          if (_level->emptyLevel(level)) {
alpar@404
   847
            // Calculation error
alpar@404
   848
            _level->liftToTop(level);
alpar@404
   849
          }
alpar@404
   850
        } else {
alpar@404
   851
          _level->deactivate(n);
alpar@404
   852
        }
alpar@404
   853
alpar@404
   854
      }
alpar@404
   855
    }
alpar@404
   856
alpar@404
   857
    /// \brief Runs the preflow algorithm.
alpar@404
   858
    ///
alpar@404
   859
    /// Runs the preflow algorithm.
alpar@404
   860
    /// \note pf.run() is just a shortcut of the following code.
alpar@404
   861
    /// \code
alpar@404
   862
    ///   pf.init();
alpar@404
   863
    ///   pf.startFirstPhase();
alpar@404
   864
    ///   pf.startSecondPhase();
alpar@404
   865
    /// \endcode
alpar@404
   866
    void run() {
alpar@404
   867
      init();
alpar@404
   868
      startFirstPhase();
alpar@404
   869
      startSecondPhase();
alpar@404
   870
    }
alpar@404
   871
alpar@404
   872
    /// \brief Runs the preflow algorithm to compute the minimum cut.
alpar@404
   873
    ///
alpar@404
   874
    /// Runs the preflow algorithm to compute the minimum cut.
alpar@404
   875
    /// \note pf.runMinCut() is just a shortcut of the following code.
alpar@404
   876
    /// \code
alpar@404
   877
    ///   pf.init();
alpar@404
   878
    ///   pf.startFirstPhase();
alpar@404
   879
    /// \endcode
alpar@404
   880
    void runMinCut() {
alpar@404
   881
      init();
alpar@404
   882
      startFirstPhase();
alpar@404
   883
    }
alpar@404
   884
alpar@404
   885
    /// @}
alpar@404
   886
alpar@404
   887
    /// \name Query Functions
kpeter@408
   888
    /// The results of the preflow algorithm can be obtained using these
alpar@404
   889
    /// functions.\n
kpeter@408
   890
    /// Either one of the \ref run() "run*()" functions or one of the
kpeter@408
   891
    /// \ref startFirstPhase() "start*()" functions should be called
kpeter@408
   892
    /// before using them.
alpar@404
   893
alpar@404
   894
    ///@{
alpar@404
   895
alpar@404
   896
    /// \brief Returns the value of the maximum flow.
alpar@404
   897
    ///
alpar@404
   898
    /// Returns the value of the maximum flow by returning the excess
kpeter@408
   899
    /// of the target node. This value equals to the value of
kpeter@408
   900
    /// the maximum flow already after the first phase of the algorithm.
kpeter@408
   901
    ///
kpeter@408
   902
    /// \pre Either \ref run() or \ref init() must be called before
kpeter@408
   903
    /// using this function.
kpeter@688
   904
    Value flowValue() const {
alpar@404
   905
      return (*_excess)[_target];
alpar@404
   906
    }
alpar@404
   907
kpeter@688
   908
    /// \brief Returns the flow value on the given arc.
alpar@404
   909
    ///
kpeter@688
   910
    /// Returns the flow value on the given arc. This method can
kpeter@408
   911
    /// be called after the second phase of the algorithm.
kpeter@408
   912
    ///
kpeter@408
   913
    /// \pre Either \ref run() or \ref init() must be called before
kpeter@408
   914
    /// using this function.
kpeter@688
   915
    Value flow(const Arc& arc) const {
kpeter@408
   916
      return (*_flow)[arc];
kpeter@408
   917
    }
kpeter@408
   918
kpeter@408
   919
    /// \brief Returns a const reference to the flow map.
kpeter@408
   920
    ///
kpeter@408
   921
    /// Returns a const reference to the arc map storing the found flow.
kpeter@408
   922
    /// This method can be called after the second phase of the algorithm.
kpeter@408
   923
    ///
kpeter@408
   924
    /// \pre Either \ref run() or \ref init() must be called before
kpeter@408
   925
    /// using this function.
kpeter@437
   926
    const FlowMap& flowMap() const {
kpeter@408
   927
      return *_flow;
kpeter@408
   928
    }
kpeter@408
   929
kpeter@408
   930
    /// \brief Returns \c true when the node is on the source side of the
kpeter@408
   931
    /// minimum cut.
kpeter@408
   932
    ///
kpeter@408
   933
    /// Returns true when the node is on the source side of the found
kpeter@408
   934
    /// minimum cut. This method can be called both after running \ref
alpar@404
   935
    /// startFirstPhase() and \ref startSecondPhase().
kpeter@408
   936
    ///
kpeter@408
   937
    /// \pre Either \ref run() or \ref init() must be called before
kpeter@408
   938
    /// using this function.
alpar@404
   939
    bool minCut(const Node& node) const {
alpar@404
   940
      return ((*_level)[node] == _level->maxLevel()) == _phase;
alpar@404
   941
    }
alpar@404
   942
kpeter@408
   943
    /// \brief Gives back a minimum value cut.
alpar@404
   944
    ///
kpeter@408
   945
    /// Sets \c cutMap to the characteristic vector of a minimum value
kpeter@408
   946
    /// cut. \c cutMap should be a \ref concepts::WriteMap "writable"
kpeter@408
   947
    /// node map with \c bool (or convertible) value type.
kpeter@408
   948
    ///
kpeter@408
   949
    /// This method can be called both after running \ref startFirstPhase()
kpeter@408
   950
    /// and \ref startSecondPhase(). The result after the second phase
kpeter@408
   951
    /// could be slightly different if inexact computation is used.
kpeter@408
   952
    ///
kpeter@408
   953
    /// \note This function calls \ref minCut() for each node, so it runs in
kpeter@606
   954
    /// O(n) time.
kpeter@408
   955
    ///
kpeter@408
   956
    /// \pre Either \ref run() or \ref init() must be called before
kpeter@408
   957
    /// using this function.
alpar@404
   958
    template <typename CutMap>
alpar@404
   959
    void minCutMap(CutMap& cutMap) const {
alpar@404
   960
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@404
   961
        cutMap.set(n, minCut(n));
alpar@404
   962
      }
alpar@404
   963
    }
alpar@404
   964
alpar@404
   965
    /// @}
alpar@404
   966
  };
alpar@404
   967
}
alpar@404
   968
alpar@404
   969
#endif