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