lemon/suurballe.h
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 584 33c6b6e755cd
child 851 c67e235c832f
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
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
  ///
alpar@345
    58
  /// \warning Length values should be \e non-negative \e integers.
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@623
   255
    {
kpeter@623
   256
      LEMON_ASSERT(std::numeric_limits<Length>::is_integer,
kpeter@623
   257
        "The length type of Suurballe must be integer");
kpeter@623
   258
    }
alpar@345
   259
alpar@345
   260
    /// Destructor.
alpar@345
   261
    ~Suurballe() {
alpar@345
   262
      if (_local_flow) delete _flow;
alpar@345
   263
      if (_local_potential) delete _potential;
alpar@345
   264
      delete _dijkstra;
alpar@345
   265
    }
alpar@345
   266
kpeter@346
   267
    /// \brief Set the flow map.
alpar@345
   268
    ///
kpeter@346
   269
    /// This function sets the flow map.
kpeter@623
   270
    /// If it is not used before calling \ref run() or \ref init(),
kpeter@623
   271
    /// an instance will be allocated automatically. The destructor
kpeter@623
   272
    /// deallocates this automatically allocated map, of course.
alpar@345
   273
    ///
kpeter@623
   274
    /// The found flow contains only 0 and 1 values, since it is the
kpeter@623
   275
    /// union of the found arc-disjoint paths.
alpar@345
   276
    ///
kpeter@559
   277
    /// \return <tt>(*this)</tt>
alpar@345
   278
    Suurballe& flowMap(FlowMap &map) {
alpar@345
   279
      if (_local_flow) {
alpar@345
   280
        delete _flow;
alpar@345
   281
        _local_flow = false;
alpar@345
   282
      }
alpar@345
   283
      _flow = &map;
alpar@345
   284
      return *this;
alpar@345
   285
    }
alpar@345
   286
kpeter@346
   287
    /// \brief Set the potential map.
alpar@345
   288
    ///
kpeter@346
   289
    /// This function sets the potential map.
kpeter@623
   290
    /// If it is not used before calling \ref run() or \ref init(),
kpeter@623
   291
    /// an instance will be allocated automatically. The destructor
kpeter@623
   292
    /// deallocates this automatically allocated map, of course.
alpar@345
   293
    ///
kpeter@623
   294
    /// The node potentials provide the dual solution of the underlying
kpeter@623
   295
    /// \ref min_cost_flow "minimum cost flow problem".
alpar@345
   296
    ///
kpeter@559
   297
    /// \return <tt>(*this)</tt>
alpar@345
   298
    Suurballe& potentialMap(PotentialMap &map) {
alpar@345
   299
      if (_local_potential) {
alpar@345
   300
        delete _potential;
alpar@345
   301
        _local_potential = false;
alpar@345
   302
      }
alpar@345
   303
      _potential = &map;
alpar@345
   304
      return *this;
alpar@345
   305
    }
alpar@345
   306
kpeter@584
   307
    /// \name Execution Control
alpar@345
   308
    /// The simplest way to execute the algorithm is to call the run()
alpar@345
   309
    /// function.
alpar@345
   310
    /// \n
alpar@345
   311
    /// If you only need the flow that is the union of the found
alpar@345
   312
    /// arc-disjoint paths, you may call init() and findFlow().
alpar@345
   313
alpar@345
   314
    /// @{
alpar@345
   315
kpeter@346
   316
    /// \brief Run the algorithm.
alpar@345
   317
    ///
kpeter@346
   318
    /// This function runs the algorithm.
alpar@345
   319
    ///
kpeter@623
   320
    /// \param s The source node.
kpeter@623
   321
    /// \param t The target node.
alpar@345
   322
    /// \param k The number of paths to be found.
alpar@345
   323
    ///
kpeter@346
   324
    /// \return \c k if there are at least \c k arc-disjoint paths from
kpeter@346
   325
    /// \c s to \c t in the digraph. Otherwise it returns the number of
alpar@345
   326
    /// arc-disjoint paths found.
alpar@345
   327
    ///
kpeter@623
   328
    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
kpeter@623
   329
    /// just a shortcut of the following code.
alpar@345
   330
    /// \code
kpeter@623
   331
    ///   s.init(s);
kpeter@623
   332
    ///   s.findFlow(t, k);
alpar@345
   333
    ///   s.findPaths();
alpar@345
   334
    /// \endcode
kpeter@623
   335
    int run(const Node& s, const Node& t, int k = 2) {
kpeter@623
   336
      init(s);
kpeter@623
   337
      findFlow(t, k);
alpar@345
   338
      findPaths();
alpar@345
   339
      return _path_num;
alpar@345
   340
    }
alpar@345
   341
kpeter@346
   342
    /// \brief Initialize the algorithm.
alpar@345
   343
    ///
kpeter@346
   344
    /// This function initializes the algorithm.
kpeter@623
   345
    ///
kpeter@623
   346
    /// \param s The source node.
kpeter@623
   347
    void init(const Node& s) {
kpeter@623
   348
      _source = s;
kpeter@623
   349
kpeter@346
   350
      // Initialize maps
alpar@345
   351
      if (!_flow) {
alpar@345
   352
        _flow = new FlowMap(_graph);
alpar@345
   353
        _local_flow = true;
alpar@345
   354
      }
alpar@345
   355
      if (!_potential) {
alpar@345
   356
        _potential = new PotentialMap(_graph);
alpar@345
   357
        _local_potential = true;
alpar@345
   358
      }
alpar@345
   359
      for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
alpar@345
   360
      for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
alpar@345
   361
    }
alpar@345
   362
kpeter@623
   363
    /// \brief Execute the algorithm to find an optimal flow.
alpar@345
   364
    ///
kpeter@346
   365
    /// This function executes the successive shortest path algorithm to
kpeter@623
   366
    /// find a minimum cost flow, which is the union of \c k (or less)
alpar@345
   367
    /// arc-disjoint paths.
alpar@345
   368
    ///
kpeter@623
   369
    /// \param t The target node.
kpeter@623
   370
    /// \param k The number of paths to be found.
kpeter@623
   371
    ///
kpeter@346
   372
    /// \return \c k if there are at least \c k arc-disjoint paths from
kpeter@623
   373
    /// the source node to the given node \c t in the digraph.
kpeter@623
   374
    /// Otherwise it returns the number of arc-disjoint paths found.
alpar@345
   375
    ///
alpar@345
   376
    /// \pre \ref init() must be called before using this function.
kpeter@623
   377
    int findFlow(const Node& t, int k = 2) {
kpeter@623
   378
      _target = t;
kpeter@623
   379
      _dijkstra =
kpeter@623
   380
        new ResidualDijkstra( _graph, *_flow, _length, *_potential, _pred,
kpeter@623
   381
                              _source, _target );
kpeter@623
   382
kpeter@346
   383
      // Find shortest paths
alpar@345
   384
      _path_num = 0;
alpar@345
   385
      while (_path_num < k) {
kpeter@346
   386
        // Run Dijkstra
alpar@345
   387
        if (!_dijkstra->run()) break;
alpar@345
   388
        ++_path_num;
alpar@345
   389
kpeter@346
   390
        // Set the flow along the found shortest path
alpar@345
   391
        Node u = _target;
alpar@345
   392
        Arc e;
alpar@345
   393
        while ((e = _pred[u]) != INVALID) {
alpar@345
   394
          if (u == _graph.target(e)) {
alpar@345
   395
            (*_flow)[e] = 1;
alpar@345
   396
            u = _graph.source(e);
alpar@345
   397
          } else {
alpar@345
   398
            (*_flow)[e] = 0;
alpar@345
   399
            u = _graph.target(e);
alpar@345
   400
          }
alpar@345
   401
        }
alpar@345
   402
      }
alpar@345
   403
      return _path_num;
alpar@345
   404
    }
alpar@440
   405
kpeter@346
   406
    /// \brief Compute the paths from the flow.
alpar@345
   407
    ///
kpeter@623
   408
    /// This function computes the paths from the found minimum cost flow,
kpeter@623
   409
    /// which is the union of some arc-disjoint paths.
alpar@345
   410
    ///
alpar@345
   411
    /// \pre \ref init() and \ref findFlow() must be called before using
alpar@345
   412
    /// this function.
alpar@345
   413
    void findPaths() {
alpar@345
   414
      FlowMap res_flow(_graph);
kpeter@346
   415
      for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
alpar@345
   416
alpar@345
   417
      paths.clear();
alpar@345
   418
      paths.resize(_path_num);
alpar@345
   419
      for (int i = 0; i < _path_num; ++i) {
alpar@345
   420
        Node n = _source;
alpar@345
   421
        while (n != _target) {
alpar@345
   422
          OutArcIt e(_graph, n);
alpar@345
   423
          for ( ; res_flow[e] == 0; ++e) ;
alpar@345
   424
          n = _graph.target(e);
alpar@345
   425
          paths[i].addBack(e);
alpar@345
   426
          res_flow[e] = 0;
alpar@345
   427
        }
alpar@345
   428
      }
alpar@345
   429
    }
alpar@345
   430
alpar@345
   431
    /// @}
alpar@345
   432
alpar@345
   433
    /// \name Query Functions
kpeter@346
   434
    /// The results of the algorithm can be obtained using these
alpar@345
   435
    /// functions.
alpar@345
   436
    /// \n The algorithm should be executed before using them.
alpar@345
   437
alpar@345
   438
    /// @{
alpar@345
   439
kpeter@623
   440
    /// \brief Return the total length of the found paths.
kpeter@623
   441
    ///
kpeter@623
   442
    /// This function returns the total length of the found paths, i.e.
kpeter@623
   443
    /// the total cost of the found flow.
kpeter@623
   444
    /// The complexity of the function is O(e).
kpeter@623
   445
    ///
kpeter@623
   446
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@623
   447
    /// this function.
kpeter@623
   448
    Length totalLength() const {
kpeter@623
   449
      Length c = 0;
kpeter@623
   450
      for (ArcIt e(_graph); e != INVALID; ++e)
kpeter@623
   451
        c += (*_flow)[e] * _length[e];
kpeter@623
   452
      return c;
kpeter@623
   453
    }
kpeter@623
   454
kpeter@623
   455
    /// \brief Return the flow value on the given arc.
kpeter@623
   456
    ///
kpeter@623
   457
    /// This function returns the flow value on the given arc.
kpeter@623
   458
    /// It is \c 1 if the arc is involved in one of the found arc-disjoint
kpeter@623
   459
    /// paths, otherwise it is \c 0.
kpeter@623
   460
    ///
kpeter@623
   461
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@623
   462
    /// this function.
kpeter@623
   463
    int flow(const Arc& arc) const {
kpeter@623
   464
      return (*_flow)[arc];
kpeter@623
   465
    }
kpeter@623
   466
kpeter@623
   467
    /// \brief Return a const reference to an arc map storing the
alpar@345
   468
    /// found flow.
alpar@345
   469
    ///
kpeter@623
   470
    /// This function returns a const reference to an arc map storing
kpeter@346
   471
    /// the flow that is the union of the found arc-disjoint paths.
alpar@345
   472
    ///
kpeter@346
   473
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   474
    /// this function.
alpar@345
   475
    const FlowMap& flowMap() const {
alpar@345
   476
      return *_flow;
alpar@345
   477
    }
alpar@345
   478
kpeter@346
   479
    /// \brief Return the potential of the given node.
alpar@345
   480
    ///
kpeter@346
   481
    /// This function returns the potential of the given node.
kpeter@623
   482
    /// The node potentials provide the dual solution of the
kpeter@623
   483
    /// underlying \ref min_cost_flow "minimum cost flow problem".
alpar@345
   484
    ///
kpeter@346
   485
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   486
    /// this function.
alpar@345
   487
    Length potential(const Node& node) const {
alpar@345
   488
      return (*_potential)[node];
alpar@345
   489
    }
alpar@345
   490
kpeter@623
   491
    /// \brief Return a const reference to a node map storing the
kpeter@623
   492
    /// found potentials (the dual solution).
alpar@345
   493
    ///
kpeter@623
   494
    /// This function returns a const reference to a node map storing
kpeter@623
   495
    /// the found potentials that provide the dual solution of the
kpeter@623
   496
    /// underlying \ref min_cost_flow "minimum cost flow problem".
alpar@345
   497
    ///
kpeter@346
   498
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   499
    /// this function.
kpeter@623
   500
    const PotentialMap& potentialMap() const {
kpeter@623
   501
      return *_potential;
alpar@345
   502
    }
alpar@345
   503
kpeter@346
   504
    /// \brief Return the number of the found paths.
alpar@345
   505
    ///
kpeter@346
   506
    /// This function returns the number of the found paths.
alpar@345
   507
    ///
kpeter@346
   508
    /// \pre \ref run() or \ref findFlow() must be called before using
kpeter@346
   509
    /// this function.
alpar@345
   510
    int pathNum() const {
alpar@345
   511
      return _path_num;
alpar@345
   512
    }
alpar@345
   513
kpeter@346
   514
    /// \brief Return a const reference to the specified path.
alpar@345
   515
    ///
kpeter@346
   516
    /// This function returns a const reference to the specified path.
alpar@345
   517
    ///
kpeter@623
   518
    /// \param i The function returns the <tt>i</tt>-th path.
alpar@345
   519
    /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
alpar@345
   520
    ///
kpeter@346
   521
    /// \pre \ref run() or \ref findPaths() must be called before using
kpeter@346
   522
    /// this function.
alpar@345
   523
    Path path(int i) const {
alpar@345
   524
      return paths[i];
alpar@345
   525
    }
alpar@345
   526
alpar@345
   527
    /// @}
alpar@345
   528
alpar@345
   529
  }; //class Suurballe
alpar@345
   530
alpar@345
   531
  ///@}
alpar@345
   532
alpar@345
   533
} //namespace lemon
alpar@345
   534
alpar@345
   535
#endif //LEMON_SUURBALLE_H