lemon/suurballe.h
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 894 bb70ad62c95f
parent 851 c67e235c832f
child 853 ec0b1b423b8b
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@440
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@345
     2
 *
alpar@440
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@345
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
alpar@345
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@345
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@345
     8
 *
alpar@345
     9
 * Permission to use, modify and distribute this software is granted
alpar@345
    10
 * provided that this copyright notice appears in all copies. For
alpar@345
    11
 * precise terms see the accompanying LICENSE file.
alpar@345
    12
 *
alpar@345
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@345
    14
 * express or implied, and with no claim as to its suitability for any
alpar@345
    15
 * purpose.
alpar@345
    16
 *
alpar@345
    17
 */
alpar@345
    18
alpar@345
    19
#ifndef LEMON_SUURBALLE_H
alpar@345
    20
#define LEMON_SUURBALLE_H
alpar@345
    21
alpar@345
    22
///\ingroup shortest_path
alpar@345
    23
///\file
alpar@345
    24
///\brief An algorithm for finding arc-disjoint paths between two
alpar@345
    25
/// nodes having minimum total length.
alpar@345
    26
alpar@345
    27
#include <vector>
kpeter@623
    28
#include <limits>
alpar@345
    29
#include <lemon/bin_heap.h>
alpar@345
    30
#include <lemon/path.h>
deba@519
    31
#include <lemon/list_graph.h>
deba@519
    32
#include <lemon/maps.h>
alpar@345
    33
alpar@345
    34
namespace lemon {
alpar@345
    35
alpar@345
    36
  /// \addtogroup shortest_path
alpar@345
    37
  /// @{
alpar@345
    38
kpeter@346
    39
  /// \brief Algorithm for finding arc-disjoint paths between two nodes
kpeter@346
    40
  /// having minimum total length.
alpar@345
    41
  ///
alpar@345
    42
  /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
alpar@345
    43
  /// finding arc-disjoint paths having minimum total length (cost)
kpeter@346
    44
  /// from a given source node to a given target node in a digraph.
alpar@345
    45
  ///
kpeter@623
    46
  /// Note that this problem is a special case of the \ref min_cost_flow
kpeter@623
    47
  /// "minimum cost flow problem". This implementation is actually an
kpeter@623
    48
  /// efficient specialized version of the \ref CapacityScaling
kpeter@623
    49
  /// "Successive Shortest Path" algorithm directly for this problem.
kpeter@623
    50
  /// Therefore this class provides query functions for flow values and
kpeter@623
    51
  /// node potentials (the dual solution) just like the minimum cost flow
kpeter@623
    52
  /// algorithms.
alpar@345
    53
  ///
kpeter@559
    54
  /// \tparam GR The digraph type the algorithm runs on.
kpeter@623
    55
  /// \tparam LEN The type of the length map.
kpeter@623
    56
  /// The default value is <tt>GR::ArcMap<int></tt>.
alpar@345
    57
  ///
kpeter@852
    58
  /// \warning Length values should be \e non-negative.
alpar@345
    59
  ///
alpar@345
    60
  /// \note For finding node-disjoint paths this algorithm can be used
kpeter@623
    61
  /// along with the \ref SplitNodes adaptor.
kpeter@346
    62
#ifdef DOXYGEN
kpeter@559
    63
  template <typename GR, typename LEN>
kpeter@346
    64
#else
kpeter@623
    65
  template < typename GR,
kpeter@559
    66
             typename LEN = typename GR::template ArcMap<int> >
kpeter@346
    67
#endif
alpar@345
    68
  class Suurballe
alpar@345
    69
  {
kpeter@559
    70
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
alpar@345
    71
alpar@345
    72
    typedef ConstMap<Arc, int> ConstArcMap;
kpeter@559
    73
    typedef typename GR::template NodeMap<Arc> PredMap;
alpar@345
    74
alpar@345
    75
  public:
alpar@345
    76
kpeter@559
    77
    /// The type of the digraph the algorithm runs on.
kpeter@559
    78
    typedef GR Digraph;
kpeter@559
    79
    /// The type of the length map.
kpeter@559
    80
    typedef LEN LengthMap;
kpeter@559
    81
    /// The type of the lengths.
kpeter@559
    82
    typedef typename LengthMap::Value Length;
kpeter@623
    83
#ifdef DOXYGEN
kpeter@623
    84
    /// The type of the flow map.
kpeter@623
    85
    typedef GR::ArcMap<int> FlowMap;
kpeter@623
    86
    /// The type of the potential map.
kpeter@623
    87
    typedef GR::NodeMap<Length> PotentialMap;
kpeter@623
    88
#else
alpar@345
    89
    /// The type of the flow map.
alpar@345
    90
    typedef typename Digraph::template ArcMap<int> FlowMap;
alpar@345
    91
    /// The type of the potential map.
alpar@345
    92
    typedef typename Digraph::template NodeMap<Length> PotentialMap;
kpeter@623
    93
#endif
kpeter@623
    94
alpar@345
    95
    /// The type of the path structures.
kpeter@623
    96
    typedef SimplePath<GR> Path;
alpar@345
    97
alpar@345
    98
  private:
alpar@440
    99
kpeter@623
   100
    // ResidualDijkstra is a special implementation of the
kpeter@623
   101
    // Dijkstra algorithm for finding shortest paths in the
kpeter@623
   102
    // residual network with respect to the reduced arc lengths
kpeter@623
   103
    // and modifying the node potentials according to the
kpeter@623
   104
    // distance of the nodes.
alpar@345
   105
    class ResidualDijkstra
alpar@345
   106
    {
alpar@345
   107
      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
alpar@345
   108
      typedef BinHeap<Length, HeapCrossRef> Heap;
alpar@345
   109
alpar@345
   110
    private:
alpar@345
   111
kpeter@346
   112
      // The digraph the algorithm runs on
alpar@345
   113
      const Digraph &_graph;
alpar@345
   114
alpar@345
   115
      // The main maps
alpar@345
   116
      const FlowMap &_flow;
alpar@345
   117
      const LengthMap &_length;
alpar@345
   118
      PotentialMap &_potential;
alpar@345
   119
alpar@345
   120
      // The distance map
alpar@345
   121
      PotentialMap _dist;
alpar@345
   122
      // The pred arc map
alpar@345
   123
      PredMap &_pred;
alpar@345
   124
      // The processed (i.e. permanently labeled) nodes
alpar@345
   125
      std::vector<Node> _proc_nodes;
alpar@440
   126
alpar@345
   127
      Node _s;
alpar@345
   128
      Node _t;
alpar@345
   129
alpar@345
   130
    public:
alpar@345
   131
alpar@345
   132
      /// Constructor.
kpeter@623
   133
      ResidualDijkstra( const Digraph &graph,
alpar@345
   134
                        const FlowMap &flow,
alpar@345
   135
                        const LengthMap &length,
alpar@345
   136
                        PotentialMap &potential,
alpar@345
   137
                        PredMap &pred,
alpar@345
   138
                        Node s, Node t ) :
kpeter@623
   139
        _graph(graph), _flow(flow), _length(length), _potential(potential),
kpeter@623
   140
        _dist(graph), _pred(pred), _s(s), _t(t) {}
alpar@345
   141
kpeter@346
   142
      /// \brief Run the algorithm. It returns \c true if a path is found
alpar@345
   143
      /// from the source node to the target node.
alpar@345
   144
      bool run() {
alpar@345
   145
        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
alpar@345
   146
        Heap heap(heap_cross_ref);
alpar@345
   147
        heap.push(_s, 0);
alpar@345
   148
        _pred[_s] = INVALID;
alpar@345
   149
        _proc_nodes.clear();
alpar@345
   150
kpeter@346
   151
        // Process nodes
alpar@345
   152
        while (!heap.empty() && heap.top() != _t) {
alpar@345
   153
          Node u = heap.top(), v;
alpar@345
   154
          Length d = heap.prio() + _potential[u], nd;
alpar@345
   155
          _dist[u] = heap.prio();
alpar@345
   156
          heap.pop();
alpar@345
   157
          _proc_nodes.push_back(u);
alpar@345
   158
kpeter@346
   159
          // Traverse outgoing arcs
alpar@345
   160
          for (OutArcIt e(_graph, u); e != INVALID; ++e) {
alpar@345
   161
            if (_flow[e] == 0) {
alpar@345
   162
              v = _graph.target(e);
alpar@345
   163
              switch(heap.state(v)) {
alpar@345
   164
              case Heap::PRE_HEAP:
alpar@345
   165
                heap.push(v, d + _length[e] - _potential[v]);
alpar@345
   166
                _pred[v] = e;
alpar@345
   167
                break;
alpar@345
   168
              case Heap::IN_HEAP:
alpar@345
   169
                nd = d + _length[e] - _potential[v];
alpar@345
   170
                if (nd < heap[v]) {
alpar@345
   171
                  heap.decrease(v, nd);
alpar@345
   172
                  _pred[v] = e;
alpar@345
   173
                }
alpar@345
   174
                break;
alpar@345
   175
              case Heap::POST_HEAP:
alpar@345
   176
                break;
alpar@345
   177
              }
alpar@345
   178
            }
alpar@345
   179
          }
alpar@345
   180
kpeter@346
   181
          // Traverse incoming arcs
alpar@345
   182
          for (InArcIt e(_graph, u); e != INVALID; ++e) {
alpar@345
   183
            if (_flow[e] == 1) {
alpar@345
   184
              v = _graph.source(e);
alpar@345
   185
              switch(heap.state(v)) {
alpar@345
   186
              case Heap::PRE_HEAP:
alpar@345
   187
                heap.push(v, d - _length[e] - _potential[v]);
alpar@345
   188
                _pred[v] = e;
alpar@345
   189
                break;
alpar@345
   190
              case Heap::IN_HEAP:
alpar@345
   191
                nd = d - _length[e] - _potential[v];
alpar@345
   192
                if (nd < heap[v]) {
alpar@345
   193
                  heap.decrease(v, nd);
alpar@345
   194
                  _pred[v] = e;
alpar@345
   195
                }
alpar@345
   196
                break;
alpar@345
   197
              case Heap::POST_HEAP:
alpar@345
   198
                break;
alpar@345
   199
              }
alpar@345
   200
            }
alpar@345
   201
          }
alpar@345
   202
        }
alpar@345
   203
        if (heap.empty()) return false;
alpar@345
   204
kpeter@346
   205
        // Update potentials of processed nodes
alpar@345
   206
        Length t_dist = heap.prio();
alpar@345
   207
        for (int i = 0; i < int(_proc_nodes.size()); ++i)
alpar@345
   208
          _potential[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
alpar@345
   209
        return true;
alpar@345
   210
      }
alpar@345
   211
alpar@345
   212
    }; //class ResidualDijkstra
alpar@345
   213
alpar@345
   214
  private:
alpar@345
   215
kpeter@346
   216
    // The digraph the algorithm runs on
alpar@345
   217
    const Digraph &_graph;
alpar@345
   218
    // The length map
alpar@345
   219
    const LengthMap &_length;
alpar@440
   220
alpar@345
   221
    // Arc map of the current flow
alpar@345
   222
    FlowMap *_flow;
alpar@345
   223
    bool _local_flow;
alpar@345
   224
    // Node map of the current potentials
alpar@345
   225
    PotentialMap *_potential;
alpar@345
   226
    bool _local_potential;
alpar@345
   227
alpar@345
   228
    // The source node
alpar@345
   229
    Node _source;
alpar@345
   230
    // The target node
alpar@345
   231
    Node _target;
alpar@345
   232
alpar@345
   233
    // Container to store the found paths
alpar@345
   234
    std::vector< SimplePath<Digraph> > paths;
alpar@345
   235
    int _path_num;
alpar@345
   236
alpar@345
   237
    // The pred arc map
alpar@345
   238
    PredMap _pred;
alpar@345
   239
    // Implementation of the Dijkstra algorithm for finding augmenting
alpar@345
   240
    // shortest paths in the residual network
alpar@345
   241
    ResidualDijkstra *_dijkstra;
alpar@345
   242
alpar@345
   243
  public:
alpar@345
   244
alpar@345
   245
    /// \brief Constructor.
alpar@345
   246
    ///
alpar@345
   247
    /// Constructor.
alpar@345
   248
    ///
kpeter@623
   249
    /// \param graph The digraph the algorithm runs on.
alpar@345
   250
    /// \param length The length (cost) values of the arcs.
kpeter@623
   251
    Suurballe( const Digraph &graph,
kpeter@623
   252
               const LengthMap &length ) :
kpeter@623
   253
      _graph(graph), _length(length), _flow(0), _local_flow(false),
kpeter@623
   254
      _potential(0), _local_potential(false), _pred(graph)
kpeter@852
   255
    {}
alpar@345
   256
alpar@345
   257
    /// Destructor.
alpar@345
   258
    ~Suurballe() {
alpar@345
   259
      if (_local_flow) delete _flow;
alpar@345
   260
      if (_local_potential) delete _potential;
alpar@345
   261
      delete _dijkstra;
alpar@345
   262
    }
alpar@345
   263
kpeter@346
   264
    /// \brief Set the flow map.
alpar@345
   265
    ///
kpeter@346
   266
    /// This function sets the flow map.
kpeter@623
   267
    /// If it is not used before calling \ref run() or \ref init(),
kpeter@623
   268
    /// an instance will be allocated automatically. The destructor
kpeter@623
   269
    /// deallocates this automatically allocated map, of course.
alpar@345
   270
    ///
kpeter@623
   271
    /// The found flow contains only 0 and 1 values, since it is the
kpeter@623
   272
    /// union of the found arc-disjoint paths.
alpar@345
   273
    ///
kpeter@559
   274
    /// \return <tt>(*this)</tt>
alpar@345
   275
    Suurballe& flowMap(FlowMap &map) {
alpar@345
   276
      if (_local_flow) {
alpar@345
   277
        delete _flow;
alpar@345
   278
        _local_flow = false;
alpar@345
   279
      }
alpar@345
   280
      _flow = &map;
alpar@345
   281
      return *this;
alpar@345
   282
    }
alpar@345
   283
kpeter@346
   284
    /// \brief Set the potential map.
alpar@345
   285
    ///
kpeter@346
   286
    /// This function sets the potential map.
kpeter@623
   287
    /// If it is not used before calling \ref run() or \ref init(),
kpeter@623
   288
    /// an instance will be allocated automatically. The destructor
kpeter@623
   289
    /// deallocates this automatically allocated map, of course.
alpar@345
   290
    ///
kpeter@623
   291
    /// The node potentials provide the dual solution of the underlying
kpeter@623
   292
    /// \ref min_cost_flow "minimum cost flow problem".
alpar@345
   293
    ///
kpeter@559
   294
    /// \return <tt>(*this)</tt>
alpar@345
   295
    Suurballe& potentialMap(PotentialMap &map) {
alpar@345
   296
      if (_local_potential) {
alpar@345
   297
        delete _potential;
alpar@345
   298
        _local_potential = false;
alpar@345
   299
      }
alpar@345
   300
      _potential = &map;
alpar@345
   301
      return *this;
alpar@345
   302
    }
alpar@345
   303
kpeter@584
   304
    /// \name Execution Control
alpar@345
   305
    /// The simplest way to execute the algorithm is to call the run()
alpar@345
   306
    /// function.
alpar@345
   307
    /// \n
alpar@345
   308
    /// If you only need the flow that is the union of the found
alpar@345
   309
    /// arc-disjoint paths, you may call init() and findFlow().
alpar@345
   310
alpar@345
   311
    /// @{
alpar@345
   312
kpeter@346
   313
    /// \brief Run the algorithm.
alpar@345
   314
    ///
kpeter@346
   315
    /// This function runs the algorithm.
alpar@345
   316
    ///
kpeter@623
   317
    /// \param s The source node.
kpeter@623
   318
    /// \param t The target node.
alpar@345
   319
    /// \param k The number of paths to be found.
alpar@345
   320
    ///
kpeter@346
   321
    /// \return \c k if there are at least \c k arc-disjoint paths from
kpeter@346
   322
    /// \c s to \c t in the digraph. Otherwise it returns the number of
alpar@345
   323
    /// arc-disjoint paths found.
alpar@345
   324
    ///
kpeter@623
   325
    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
kpeter@623
   326
    /// just a shortcut of the following code.
alpar@345
   327
    /// \code
kpeter@623
   328
    ///   s.init(s);
kpeter@623
   329
    ///   s.findFlow(t, k);
alpar@345
   330
    ///   s.findPaths();
alpar@345
   331
    /// \endcode
kpeter@623
   332
    int run(const Node& s, const Node& t, int k = 2) {
kpeter@623
   333
      init(s);
kpeter@623
   334
      findFlow(t, k);
alpar@345
   335
      findPaths();
alpar@345
   336
      return _path_num;
alpar@345
   337
    }
alpar@345
   338
kpeter@346
   339
    /// \brief Initialize the algorithm.
alpar@345
   340
    ///
kpeter@346
   341
    /// This function initializes the algorithm.
kpeter@623
   342
    ///
kpeter@623
   343
    /// \param s The source node.
kpeter@623
   344
    void init(const Node& s) {
kpeter@623
   345
      _source = s;
kpeter@623
   346
kpeter@346
   347
      // Initialize maps
alpar@345
   348
      if (!_flow) {
alpar@345
   349
        _flow = new FlowMap(_graph);
alpar@345
   350
        _local_flow = true;
alpar@345
   351
      }
alpar@345
   352
      if (!_potential) {
alpar@345
   353
        _potential = new PotentialMap(_graph);
alpar@345
   354
        _local_potential = true;
alpar@345
   355
      }
alpar@345
   356
      for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
alpar@345
   357
      for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
alpar@345
   358
    }
alpar@345
   359
kpeter@623
   360
    /// \brief Execute the algorithm to find an optimal flow.
alpar@345
   361
    ///
kpeter@346
   362
    /// This function executes the successive shortest path algorithm to
kpeter@623
   363
    /// find a minimum cost flow, which is the union of \c k (or less)
alpar@345
   364
    /// arc-disjoint paths.
alpar@345
   365
    ///
kpeter@623
   366
    /// \param t The target node.
kpeter@623
   367
    /// \param k The number of paths to be found.
kpeter@623
   368
    ///
kpeter@346
   369
    /// \return \c k if there are at least \c k arc-disjoint paths from
kpeter@623
   370
    /// the source node to the given node \c t in the digraph.
kpeter@623
   371
    /// Otherwise it returns the number of arc-disjoint paths found.
alpar@345
   372
    ///
alpar@345
   373
    /// \pre \ref init() must be called before using this function.
kpeter@623
   374
    int findFlow(const Node& t, int k = 2) {
kpeter@623
   375
      _target = t;
kpeter@623
   376
      _dijkstra =
kpeter@623
   377
        new ResidualDijkstra( _graph, *_flow, _length, *_potential, _pred,
kpeter@623
   378
                              _source, _target );
kpeter@623
   379
kpeter@346
   380
      // Find shortest paths
alpar@345
   381
      _path_num = 0;
alpar@345
   382
      while (_path_num < k) {
kpeter@346
   383
        // Run Dijkstra
alpar@345
   384
        if (!_dijkstra->run()) break;
alpar@345
   385
        ++_path_num;
alpar@345
   386
kpeter@346
   387
        // Set the flow along the found shortest path
alpar@345
   388
        Node u = _target;
alpar@345
   389
        Arc e;
alpar@345
   390
        while ((e = _pred[u]) != INVALID) {
alpar@345
   391
          if (u == _graph.target(e)) {
alpar@345
   392
            (*_flow)[e] = 1;
alpar@345
   393
            u = _graph.source(e);
alpar@345
   394
          } else {
alpar@345
   395
            (*_flow)[e] = 0;
alpar@345
   396
            u = _graph.target(e);
alpar@345
   397
          }
alpar@345
   398
        }
alpar@345
   399
      }
alpar@345
   400
      return _path_num;
alpar@345
   401
    }
alpar@440
   402
kpeter@346
   403
    /// \brief Compute the paths from the flow.
alpar@345
   404
    ///
kpeter@623
   405
    /// This function computes the paths from the found minimum cost flow,
kpeter@623
   406
    /// which is the union of some arc-disjoint paths.
alpar@345
   407
    ///
alpar@345
   408
    /// \pre \ref init() and \ref findFlow() must be called before using
alpar@345
   409
    /// this function.
alpar@345
   410
    void findPaths() {
alpar@345
   411
      FlowMap res_flow(_graph);
kpeter@346
   412
      for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
alpar@345
   413
alpar@345
   414
      paths.clear();
alpar@345
   415
      paths.resize(_path_num);
alpar@345
   416
      for (int i = 0; i < _path_num; ++i) {
alpar@345
   417
        Node n = _source;
alpar@345
   418
        while (n != _target) {
alpar@345
   419
          OutArcIt e(_graph, n);
alpar@345
   420
          for ( ; res_flow[e] == 0; ++e) ;
alpar@345
   421
          n = _graph.target(e);
alpar@345
   422
          paths[i].addBack(e);
alpar@345
   423
          res_flow[e] = 0;
alpar@345
   424
        }
alpar@345
   425
      }
alpar@345
   426
    }
alpar@345
   427
alpar@345
   428
    /// @}
alpar@345
   429
alpar@345
   430
    /// \name Query Functions
kpeter@346
   431
    /// The results of the algorithm can be obtained using these
alpar@345
   432
    /// functions.
alpar@345
   433
    /// \n The algorithm should be executed before using them.
alpar@345
   434
alpar@345
   435
    /// @{
alpar@345
   436
kpeter@623
   437
    /// \brief Return the total length of the found paths.
kpeter@623
   438
    ///
kpeter@623
   439
    /// This function returns the total length of the found paths, i.e.
kpeter@623
   440
    /// the total cost of the found flow.
kpeter@623
   441
    /// The complexity of the function is O(e).
kpeter@623
   442
    ///
kpeter@623
   443
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@623
   444
    /// this function.
kpeter@623
   445
    Length totalLength() const {
kpeter@623
   446
      Length c = 0;
kpeter@623
   447
      for (ArcIt e(_graph); e != INVALID; ++e)
kpeter@623
   448
        c += (*_flow)[e] * _length[e];
kpeter@623
   449
      return c;
kpeter@623
   450
    }
kpeter@623
   451
kpeter@623
   452
    /// \brief Return the flow value on the given arc.
kpeter@623
   453
    ///
kpeter@623
   454
    /// This function returns the flow value on the given arc.
kpeter@623
   455
    /// It is \c 1 if the arc is involved in one of the found arc-disjoint
kpeter@623
   456
    /// paths, otherwise it is \c 0.
kpeter@623
   457
    ///
kpeter@623
   458
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@623
   459
    /// this function.
kpeter@623
   460
    int flow(const Arc& arc) const {
kpeter@623
   461
      return (*_flow)[arc];
kpeter@623
   462
    }
kpeter@623
   463
kpeter@623
   464
    /// \brief Return a const reference to an arc map storing the
alpar@345
   465
    /// found flow.
alpar@345
   466
    ///
kpeter@623
   467
    /// This function returns a const reference to an arc map storing
kpeter@346
   468
    /// the flow that is the union of the found arc-disjoint paths.
alpar@345
   469
    ///
kpeter@346
   470
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   471
    /// this function.
alpar@345
   472
    const FlowMap& flowMap() const {
alpar@345
   473
      return *_flow;
alpar@345
   474
    }
alpar@345
   475
kpeter@346
   476
    /// \brief Return the potential of the given node.
alpar@345
   477
    ///
kpeter@346
   478
    /// This function returns the potential of the given node.
kpeter@623
   479
    /// The node potentials provide the dual solution of the
kpeter@623
   480
    /// underlying \ref min_cost_flow "minimum cost flow problem".
alpar@345
   481
    ///
kpeter@346
   482
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   483
    /// this function.
alpar@345
   484
    Length potential(const Node& node) const {
alpar@345
   485
      return (*_potential)[node];
alpar@345
   486
    }
alpar@345
   487
kpeter@623
   488
    /// \brief Return a const reference to a node map storing the
kpeter@623
   489
    /// found potentials (the dual solution).
alpar@345
   490
    ///
kpeter@623
   491
    /// This function returns a const reference to a node map storing
kpeter@623
   492
    /// the found potentials that provide the dual solution of the
kpeter@623
   493
    /// underlying \ref min_cost_flow "minimum cost flow problem".
alpar@345
   494
    ///
kpeter@346
   495
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   496
    /// this function.
kpeter@623
   497
    const PotentialMap& potentialMap() const {
kpeter@623
   498
      return *_potential;
alpar@345
   499
    }
alpar@345
   500
kpeter@346
   501
    /// \brief Return the number of the found paths.
alpar@345
   502
    ///
kpeter@346
   503
    /// This function returns the number of the found paths.
alpar@345
   504
    ///
kpeter@346
   505
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   506
    /// this function.
alpar@345
   507
    int pathNum() const {
alpar@345
   508
      return _path_num;
alpar@345
   509
    }
alpar@345
   510
kpeter@346
   511
    /// \brief Return a const reference to the specified path.
alpar@345
   512
    ///
kpeter@346
   513
    /// This function returns a const reference to the specified path.
alpar@345
   514
    ///
kpeter@623
   515
    /// \param i The function returns the <tt>i</tt>-th path.
alpar@345
   516
    /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
alpar@345
   517
    ///
kpeter@346
   518
    /// \pre \ref run() or \ref findPaths() must be called before using
kpeter@346
   519
    /// this function.
kpeter@851
   520
    const Path& path(int i) const {
alpar@345
   521
      return paths[i];
alpar@345
   522
    }
alpar@345
   523
alpar@345
   524
    /// @}
alpar@345
   525
alpar@345
   526
  }; //class Suurballe
alpar@345
   527
alpar@345
   528
  ///@}
alpar@345
   529
alpar@345
   530
} //namespace lemon
alpar@345
   531
alpar@345
   532
#endif //LEMON_SUURBALLE_H