lemon/suurballe.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 863 a93f1a27d831
child 1074 97d978243703
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2010
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_SUURBALLE_H
    20 #define LEMON_SUURBALLE_H
    21 
    22 ///\ingroup shortest_path
    23 ///\file
    24 ///\brief An algorithm for finding arc-disjoint paths between two
    25 /// nodes having minimum total length.
    26 
    27 #include <vector>
    28 #include <limits>
    29 #include <lemon/bin_heap.h>
    30 #include <lemon/path.h>
    31 #include <lemon/list_graph.h>
    32 #include <lemon/dijkstra.h>
    33 #include <lemon/maps.h>
    34 
    35 namespace lemon {
    36 
    37   /// \brief Default traits class of Suurballe algorithm.
    38   ///
    39   /// Default traits class of Suurballe algorithm.
    40   /// \tparam GR The digraph type the algorithm runs on.
    41   /// \tparam LEN The type of the length map.
    42   /// The default value is <tt>GR::ArcMap<int></tt>.
    43 #ifdef DOXYGEN
    44   template <typename GR, typename LEN>
    45 #else
    46   template < typename GR,
    47              typename LEN = typename GR::template ArcMap<int> >
    48 #endif
    49   struct SuurballeDefaultTraits
    50   {
    51     /// The type of the digraph.
    52     typedef GR Digraph;
    53     /// The type of the length map.
    54     typedef LEN LengthMap;
    55     /// The type of the lengths.
    56     typedef typename LEN::Value Length;
    57     /// The type of the flow map.
    58     typedef typename GR::template ArcMap<int> FlowMap;
    59     /// The type of the potential map.
    60     typedef typename GR::template NodeMap<Length> PotentialMap;
    61 
    62     /// \brief The path type
    63     ///
    64     /// The type used for storing the found arc-disjoint paths.
    65     /// It must conform to the \ref lemon::concepts::Path "Path" concept
    66     /// and it must have an \c addBack() function.
    67     typedef lemon::Path<Digraph> Path;
    68 
    69     /// The cross reference type used for the heap.
    70     typedef typename GR::template NodeMap<int> HeapCrossRef;
    71 
    72     /// \brief The heap type used for internal Dijkstra computations.
    73     ///
    74     /// The type of the heap used for internal Dijkstra computations.
    75     /// It must conform to the \ref lemon::concepts::Heap "Heap" concept
    76     /// and its priority type must be \c Length.
    77     typedef BinHeap<Length, HeapCrossRef> Heap;
    78   };
    79 
    80   /// \addtogroup shortest_path
    81   /// @{
    82 
    83   /// \brief Algorithm for finding arc-disjoint paths between two nodes
    84   /// having minimum total length.
    85   ///
    86   /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
    87   /// finding arc-disjoint paths having minimum total length (cost)
    88   /// from a given source node to a given target node in a digraph.
    89   ///
    90   /// Note that this problem is a special case of the \ref min_cost_flow
    91   /// "minimum cost flow problem". This implementation is actually an
    92   /// efficient specialized version of the \ref CapacityScaling
    93   /// "successive shortest path" algorithm directly for this problem.
    94   /// Therefore this class provides query functions for flow values and
    95   /// node potentials (the dual solution) just like the minimum cost flow
    96   /// algorithms.
    97   ///
    98   /// \tparam GR The digraph type the algorithm runs on.
    99   /// \tparam LEN The type of the length map.
   100   /// The default value is <tt>GR::ArcMap<int></tt>.
   101   ///
   102   /// \warning Length values should be \e non-negative.
   103   ///
   104   /// \note For finding \e node-disjoint paths, this algorithm can be used
   105   /// along with the \ref SplitNodes adaptor.
   106 #ifdef DOXYGEN
   107   template <typename GR, typename LEN, typename TR>
   108 #else
   109   template < typename GR,
   110              typename LEN = typename GR::template ArcMap<int>,
   111              typename TR = SuurballeDefaultTraits<GR, LEN> >
   112 #endif
   113   class Suurballe
   114   {
   115     TEMPLATE_DIGRAPH_TYPEDEFS(GR);
   116 
   117     typedef ConstMap<Arc, int> ConstArcMap;
   118     typedef typename GR::template NodeMap<Arc> PredMap;
   119 
   120   public:
   121 
   122     /// The type of the digraph.
   123     typedef typename TR::Digraph Digraph;
   124     /// The type of the length map.
   125     typedef typename TR::LengthMap LengthMap;
   126     /// The type of the lengths.
   127     typedef typename TR::Length Length;
   128 
   129     /// The type of the flow map.
   130     typedef typename TR::FlowMap FlowMap;
   131     /// The type of the potential map.
   132     typedef typename TR::PotentialMap PotentialMap;
   133     /// The type of the path structures.
   134     typedef typename TR::Path Path;
   135     /// The cross reference type used for the heap.
   136     typedef typename TR::HeapCrossRef HeapCrossRef;
   137     /// The heap type used for internal Dijkstra computations.
   138     typedef typename TR::Heap Heap;
   139 
   140     /// The \ref SuurballeDefaultTraits "traits class" of the algorithm.
   141     typedef TR Traits;
   142 
   143   private:
   144 
   145     // ResidualDijkstra is a special implementation of the
   146     // Dijkstra algorithm for finding shortest paths in the
   147     // residual network with respect to the reduced arc lengths
   148     // and modifying the node potentials according to the
   149     // distance of the nodes.
   150     class ResidualDijkstra
   151     {
   152     private:
   153 
   154       const Digraph &_graph;
   155       const LengthMap &_length;
   156       const FlowMap &_flow;
   157       PotentialMap &_pi;
   158       PredMap &_pred;
   159       Node _s;
   160       Node _t;
   161 
   162       PotentialMap _dist;
   163       std::vector<Node> _proc_nodes;
   164 
   165     public:
   166 
   167       // Constructor
   168       ResidualDijkstra(Suurballe &srb) :
   169         _graph(srb._graph), _length(srb._length),
   170         _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred),
   171         _s(srb._s), _t(srb._t), _dist(_graph) {}
   172 
   173       // Run the algorithm and return true if a path is found
   174       // from the source node to the target node.
   175       bool run(int cnt) {
   176         return cnt == 0 ? startFirst() : start();
   177       }
   178 
   179     private:
   180 
   181       // Execute the algorithm for the first time (the flow and potential
   182       // functions have to be identically zero).
   183       bool startFirst() {
   184         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
   185         Heap heap(heap_cross_ref);
   186         heap.push(_s, 0);
   187         _pred[_s] = INVALID;
   188         _proc_nodes.clear();
   189 
   190         // Process nodes
   191         while (!heap.empty() && heap.top() != _t) {
   192           Node u = heap.top(), v;
   193           Length d = heap.prio(), dn;
   194           _dist[u] = heap.prio();
   195           _proc_nodes.push_back(u);
   196           heap.pop();
   197 
   198           // Traverse outgoing arcs
   199           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
   200             v = _graph.target(e);
   201             switch(heap.state(v)) {
   202               case Heap::PRE_HEAP:
   203                 heap.push(v, d + _length[e]);
   204                 _pred[v] = e;
   205                 break;
   206               case Heap::IN_HEAP:
   207                 dn = d + _length[e];
   208                 if (dn < heap[v]) {
   209                   heap.decrease(v, dn);
   210                   _pred[v] = e;
   211                 }
   212                 break;
   213               case Heap::POST_HEAP:
   214                 break;
   215             }
   216           }
   217         }
   218         if (heap.empty()) return false;
   219 
   220         // Update potentials of processed nodes
   221         Length t_dist = heap.prio();
   222         for (int i = 0; i < int(_proc_nodes.size()); ++i)
   223           _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
   224         return true;
   225       }
   226 
   227       // Execute the algorithm.
   228       bool start() {
   229         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
   230         Heap heap(heap_cross_ref);
   231         heap.push(_s, 0);
   232         _pred[_s] = INVALID;
   233         _proc_nodes.clear();
   234 
   235         // Process nodes
   236         while (!heap.empty() && heap.top() != _t) {
   237           Node u = heap.top(), v;
   238           Length d = heap.prio() + _pi[u], dn;
   239           _dist[u] = heap.prio();
   240           _proc_nodes.push_back(u);
   241           heap.pop();
   242 
   243           // Traverse outgoing arcs
   244           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
   245             if (_flow[e] == 0) {
   246               v = _graph.target(e);
   247               switch(heap.state(v)) {
   248                 case Heap::PRE_HEAP:
   249                   heap.push(v, d + _length[e] - _pi[v]);
   250                   _pred[v] = e;
   251                   break;
   252                 case Heap::IN_HEAP:
   253                   dn = d + _length[e] - _pi[v];
   254                   if (dn < heap[v]) {
   255                     heap.decrease(v, dn);
   256                     _pred[v] = e;
   257                   }
   258                   break;
   259                 case Heap::POST_HEAP:
   260                   break;
   261               }
   262             }
   263           }
   264 
   265           // Traverse incoming arcs
   266           for (InArcIt e(_graph, u); e != INVALID; ++e) {
   267             if (_flow[e] == 1) {
   268               v = _graph.source(e);
   269               switch(heap.state(v)) {
   270                 case Heap::PRE_HEAP:
   271                   heap.push(v, d - _length[e] - _pi[v]);
   272                   _pred[v] = e;
   273                   break;
   274                 case Heap::IN_HEAP:
   275                   dn = d - _length[e] - _pi[v];
   276                   if (dn < heap[v]) {
   277                     heap.decrease(v, dn);
   278                     _pred[v] = e;
   279                   }
   280                   break;
   281                 case Heap::POST_HEAP:
   282                   break;
   283               }
   284             }
   285           }
   286         }
   287         if (heap.empty()) return false;
   288 
   289         // Update potentials of processed nodes
   290         Length t_dist = heap.prio();
   291         for (int i = 0; i < int(_proc_nodes.size()); ++i)
   292           _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
   293         return true;
   294       }
   295 
   296     }; //class ResidualDijkstra
   297 
   298   public:
   299 
   300     /// \name Named Template Parameters
   301     /// @{
   302 
   303     template <typename T>
   304     struct SetFlowMapTraits : public Traits {
   305       typedef T FlowMap;
   306     };
   307 
   308     /// \brief \ref named-templ-param "Named parameter" for setting
   309     /// \c FlowMap type.
   310     ///
   311     /// \ref named-templ-param "Named parameter" for setting
   312     /// \c FlowMap type.
   313     template <typename T>
   314     struct SetFlowMap
   315       : public Suurballe<GR, LEN, SetFlowMapTraits<T> > {
   316       typedef Suurballe<GR, LEN, SetFlowMapTraits<T> > Create;
   317     };
   318 
   319     template <typename T>
   320     struct SetPotentialMapTraits : public Traits {
   321       typedef T PotentialMap;
   322     };
   323 
   324     /// \brief \ref named-templ-param "Named parameter" for setting
   325     /// \c PotentialMap type.
   326     ///
   327     /// \ref named-templ-param "Named parameter" for setting
   328     /// \c PotentialMap type.
   329     template <typename T>
   330     struct SetPotentialMap
   331       : public Suurballe<GR, LEN, SetPotentialMapTraits<T> > {
   332       typedef Suurballe<GR, LEN, SetPotentialMapTraits<T> > Create;
   333     };
   334 
   335     template <typename T>
   336     struct SetPathTraits : public Traits {
   337       typedef T Path;
   338     };
   339 
   340     /// \brief \ref named-templ-param "Named parameter" for setting
   341     /// \c %Path type.
   342     ///
   343     /// \ref named-templ-param "Named parameter" for setting \c %Path type.
   344     /// It must conform to the \ref lemon::concepts::Path "Path" concept
   345     /// and it must have an \c addBack() function.
   346     template <typename T>
   347     struct SetPath
   348       : public Suurballe<GR, LEN, SetPathTraits<T> > {
   349       typedef Suurballe<GR, LEN, SetPathTraits<T> > Create;
   350     };
   351 
   352     template <typename H, typename CR>
   353     struct SetHeapTraits : public Traits {
   354       typedef H Heap;
   355       typedef CR HeapCrossRef;
   356     };
   357 
   358     /// \brief \ref named-templ-param "Named parameter" for setting
   359     /// \c Heap and \c HeapCrossRef types.
   360     ///
   361     /// \ref named-templ-param "Named parameter" for setting \c Heap
   362     /// and \c HeapCrossRef types with automatic allocation.
   363     /// They will be used for internal Dijkstra computations.
   364     /// The heap type must conform to the \ref lemon::concepts::Heap "Heap"
   365     /// concept and its priority type must be \c Length.
   366     template <typename H,
   367               typename CR = typename Digraph::template NodeMap<int> >
   368     struct SetHeap
   369       : public Suurballe<GR, LEN, SetHeapTraits<H, CR> > {
   370       typedef Suurballe<GR, LEN, SetHeapTraits<H, CR> > Create;
   371     };
   372 
   373     /// @}
   374 
   375   private:
   376 
   377     // The digraph the algorithm runs on
   378     const Digraph &_graph;
   379     // The length map
   380     const LengthMap &_length;
   381 
   382     // Arc map of the current flow
   383     FlowMap *_flow;
   384     bool _local_flow;
   385     // Node map of the current potentials
   386     PotentialMap *_potential;
   387     bool _local_potential;
   388 
   389     // The source node
   390     Node _s;
   391     // The target node
   392     Node _t;
   393 
   394     // Container to store the found paths
   395     std::vector<Path> _paths;
   396     int _path_num;
   397 
   398     // The pred arc map
   399     PredMap _pred;
   400 
   401     // Data for full init
   402     PotentialMap *_init_dist;
   403     PredMap *_init_pred;
   404     bool _full_init;
   405 
   406   protected:
   407 
   408     Suurballe() {}
   409 
   410   public:
   411 
   412     /// \brief Constructor.
   413     ///
   414     /// Constructor.
   415     ///
   416     /// \param graph The digraph the algorithm runs on.
   417     /// \param length The length (cost) values of the arcs.
   418     Suurballe( const Digraph &graph,
   419                const LengthMap &length ) :
   420       _graph(graph), _length(length), _flow(0), _local_flow(false),
   421       _potential(0), _local_potential(false), _pred(graph),
   422       _init_dist(0), _init_pred(0)
   423     {}
   424 
   425     /// Destructor.
   426     ~Suurballe() {
   427       if (_local_flow) delete _flow;
   428       if (_local_potential) delete _potential;
   429       delete _init_dist;
   430       delete _init_pred;
   431     }
   432 
   433     /// \brief Set the flow map.
   434     ///
   435     /// This function sets the flow map.
   436     /// If it is not used before calling \ref run() or \ref init(),
   437     /// an instance will be allocated automatically. The destructor
   438     /// deallocates this automatically allocated map, of course.
   439     ///
   440     /// The found flow contains only 0 and 1 values, since it is the
   441     /// union of the found arc-disjoint paths.
   442     ///
   443     /// \return <tt>(*this)</tt>
   444     Suurballe& flowMap(FlowMap &map) {
   445       if (_local_flow) {
   446         delete _flow;
   447         _local_flow = false;
   448       }
   449       _flow = &map;
   450       return *this;
   451     }
   452 
   453     /// \brief Set the potential map.
   454     ///
   455     /// This function sets the potential map.
   456     /// If it is not used before calling \ref run() or \ref init(),
   457     /// an instance will be allocated automatically. The destructor
   458     /// deallocates this automatically allocated map, of course.
   459     ///
   460     /// The node potentials provide the dual solution of the underlying
   461     /// \ref min_cost_flow "minimum cost flow problem".
   462     ///
   463     /// \return <tt>(*this)</tt>
   464     Suurballe& potentialMap(PotentialMap &map) {
   465       if (_local_potential) {
   466         delete _potential;
   467         _local_potential = false;
   468       }
   469       _potential = &map;
   470       return *this;
   471     }
   472 
   473     /// \name Execution Control
   474     /// The simplest way to execute the algorithm is to call the run()
   475     /// function.\n
   476     /// If you need to execute the algorithm many times using the same
   477     /// source node, then you may call fullInit() once and start()
   478     /// for each target node.\n
   479     /// If you only need the flow that is the union of the found
   480     /// arc-disjoint paths, then you may call findFlow() instead of
   481     /// start().
   482 
   483     /// @{
   484 
   485     /// \brief Run the algorithm.
   486     ///
   487     /// This function runs the algorithm.
   488     ///
   489     /// \param s The source node.
   490     /// \param t The target node.
   491     /// \param k The number of paths to be found.
   492     ///
   493     /// \return \c k if there are at least \c k arc-disjoint paths from
   494     /// \c s to \c t in the digraph. Otherwise it returns the number of
   495     /// arc-disjoint paths found.
   496     ///
   497     /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
   498     /// just a shortcut of the following code.
   499     /// \code
   500     ///   s.init(s);
   501     ///   s.start(t, k);
   502     /// \endcode
   503     int run(const Node& s, const Node& t, int k = 2) {
   504       init(s);
   505       start(t, k);
   506       return _path_num;
   507     }
   508 
   509     /// \brief Initialize the algorithm.
   510     ///
   511     /// This function initializes the algorithm with the given source node.
   512     ///
   513     /// \param s The source node.
   514     void init(const Node& s) {
   515       _s = s;
   516 
   517       // Initialize maps
   518       if (!_flow) {
   519         _flow = new FlowMap(_graph);
   520         _local_flow = true;
   521       }
   522       if (!_potential) {
   523         _potential = new PotentialMap(_graph);
   524         _local_potential = true;
   525       }
   526       _full_init = false;
   527     }
   528 
   529     /// \brief Initialize the algorithm and perform Dijkstra.
   530     ///
   531     /// This function initializes the algorithm and performs a full
   532     /// Dijkstra search from the given source node. It makes consecutive
   533     /// executions of \ref start() "start(t, k)" faster, since they
   534     /// have to perform %Dijkstra only k-1 times.
   535     ///
   536     /// This initialization is usually worth using instead of \ref init()
   537     /// if the algorithm is executed many times using the same source node.
   538     ///
   539     /// \param s The source node.
   540     void fullInit(const Node& s) {
   541       // Initialize maps
   542       init(s);
   543       if (!_init_dist) {
   544         _init_dist = new PotentialMap(_graph);
   545       }
   546       if (!_init_pred) {
   547         _init_pred = new PredMap(_graph);
   548       }
   549 
   550       // Run a full Dijkstra
   551       typename Dijkstra<Digraph, LengthMap>
   552         ::template SetStandardHeap<Heap>
   553         ::template SetDistMap<PotentialMap>
   554         ::template SetPredMap<PredMap>
   555         ::Create dijk(_graph, _length);
   556       dijk.distMap(*_init_dist).predMap(*_init_pred);
   557       dijk.run(s);
   558 
   559       _full_init = true;
   560     }
   561 
   562     /// \brief Execute the algorithm.
   563     ///
   564     /// This function executes the algorithm.
   565     ///
   566     /// \param t The target node.
   567     /// \param k The number of paths to be found.
   568     ///
   569     /// \return \c k if there are at least \c k arc-disjoint paths from
   570     /// \c s to \c t in the digraph. Otherwise it returns the number of
   571     /// arc-disjoint paths found.
   572     ///
   573     /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
   574     /// just a shortcut of the following code.
   575     /// \code
   576     ///   s.findFlow(t, k);
   577     ///   s.findPaths();
   578     /// \endcode
   579     int start(const Node& t, int k = 2) {
   580       findFlow(t, k);
   581       findPaths();
   582       return _path_num;
   583     }
   584 
   585     /// \brief Execute the algorithm to find an optimal flow.
   586     ///
   587     /// This function executes the successive shortest path algorithm to
   588     /// find a minimum cost flow, which is the union of \c k (or less)
   589     /// arc-disjoint paths.
   590     ///
   591     /// \param t The target node.
   592     /// \param k The number of paths to be found.
   593     ///
   594     /// \return \c k if there are at least \c k arc-disjoint paths from
   595     /// the source node to the given node \c t in the digraph.
   596     /// Otherwise it returns the number of arc-disjoint paths found.
   597     ///
   598     /// \pre \ref init() must be called before using this function.
   599     int findFlow(const Node& t, int k = 2) {
   600       _t = t;
   601       ResidualDijkstra dijkstra(*this);
   602 
   603       // Initialization
   604       for (ArcIt e(_graph); e != INVALID; ++e) {
   605         (*_flow)[e] = 0;
   606       }
   607       if (_full_init) {
   608         for (NodeIt n(_graph); n != INVALID; ++n) {
   609           (*_potential)[n] = (*_init_dist)[n];
   610         }
   611         Node u = _t;
   612         Arc e;
   613         while ((e = (*_init_pred)[u]) != INVALID) {
   614           (*_flow)[e] = 1;
   615           u = _graph.source(e);
   616         }
   617         _path_num = 1;
   618       } else {
   619         for (NodeIt n(_graph); n != INVALID; ++n) {
   620           (*_potential)[n] = 0;
   621         }
   622         _path_num = 0;
   623       }
   624 
   625       // Find shortest paths
   626       while (_path_num < k) {
   627         // Run Dijkstra
   628         if (!dijkstra.run(_path_num)) break;
   629         ++_path_num;
   630 
   631         // Set the flow along the found shortest path
   632         Node u = _t;
   633         Arc e;
   634         while ((e = _pred[u]) != INVALID) {
   635           if (u == _graph.target(e)) {
   636             (*_flow)[e] = 1;
   637             u = _graph.source(e);
   638           } else {
   639             (*_flow)[e] = 0;
   640             u = _graph.target(e);
   641           }
   642         }
   643       }
   644       return _path_num;
   645     }
   646 
   647     /// \brief Compute the paths from the flow.
   648     ///
   649     /// This function computes arc-disjoint paths from the found minimum
   650     /// cost flow, which is the union of them.
   651     ///
   652     /// \pre \ref init() and \ref findFlow() must be called before using
   653     /// this function.
   654     void findPaths() {
   655       FlowMap res_flow(_graph);
   656       for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
   657 
   658       _paths.clear();
   659       _paths.resize(_path_num);
   660       for (int i = 0; i < _path_num; ++i) {
   661         Node n = _s;
   662         while (n != _t) {
   663           OutArcIt e(_graph, n);
   664           for ( ; res_flow[e] == 0; ++e) ;
   665           n = _graph.target(e);
   666           _paths[i].addBack(e);
   667           res_flow[e] = 0;
   668         }
   669       }
   670     }
   671 
   672     /// @}
   673 
   674     /// \name Query Functions
   675     /// The results of the algorithm can be obtained using these
   676     /// functions.
   677     /// \n The algorithm should be executed before using them.
   678 
   679     /// @{
   680 
   681     /// \brief Return the total length of the found paths.
   682     ///
   683     /// This function returns the total length of the found paths, i.e.
   684     /// the total cost of the found flow.
   685     /// The complexity of the function is O(e).
   686     ///
   687     /// \pre \ref run() or \ref findFlow() must be called before using
   688     /// this function.
   689     Length totalLength() const {
   690       Length c = 0;
   691       for (ArcIt e(_graph); e != INVALID; ++e)
   692         c += (*_flow)[e] * _length[e];
   693       return c;
   694     }
   695 
   696     /// \brief Return the flow value on the given arc.
   697     ///
   698     /// This function returns the flow value on the given arc.
   699     /// It is \c 1 if the arc is involved in one of the found arc-disjoint
   700     /// paths, otherwise it is \c 0.
   701     ///
   702     /// \pre \ref run() or \ref findFlow() must be called before using
   703     /// this function.
   704     int flow(const Arc& arc) const {
   705       return (*_flow)[arc];
   706     }
   707 
   708     /// \brief Return a const reference to an arc map storing the
   709     /// found flow.
   710     ///
   711     /// This function returns a const reference to an arc map storing
   712     /// the flow that is the union of the found arc-disjoint paths.
   713     ///
   714     /// \pre \ref run() or \ref findFlow() must be called before using
   715     /// this function.
   716     const FlowMap& flowMap() const {
   717       return *_flow;
   718     }
   719 
   720     /// \brief Return the potential of the given node.
   721     ///
   722     /// This function returns the potential of the given node.
   723     /// The node potentials provide the dual solution of the
   724     /// underlying \ref min_cost_flow "minimum cost flow problem".
   725     ///
   726     /// \pre \ref run() or \ref findFlow() must be called before using
   727     /// this function.
   728     Length potential(const Node& node) const {
   729       return (*_potential)[node];
   730     }
   731 
   732     /// \brief Return a const reference to a node map storing the
   733     /// found potentials (the dual solution).
   734     ///
   735     /// This function returns a const reference to a node map storing
   736     /// the found potentials that provide the dual solution of the
   737     /// underlying \ref min_cost_flow "minimum cost flow problem".
   738     ///
   739     /// \pre \ref run() or \ref findFlow() must be called before using
   740     /// this function.
   741     const PotentialMap& potentialMap() const {
   742       return *_potential;
   743     }
   744 
   745     /// \brief Return the number of the found paths.
   746     ///
   747     /// This function returns the number of the found paths.
   748     ///
   749     /// \pre \ref run() or \ref findFlow() must be called before using
   750     /// this function.
   751     int pathNum() const {
   752       return _path_num;
   753     }
   754 
   755     /// \brief Return a const reference to the specified path.
   756     ///
   757     /// This function returns a const reference to the specified path.
   758     ///
   759     /// \param i The function returns the <tt>i</tt>-th path.
   760     /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
   761     ///
   762     /// \pre \ref run() or \ref findPaths() must be called before using
   763     /// this function.
   764     const Path& path(int i) const {
   765       return _paths[i];
   766     }
   767 
   768     /// @}
   769 
   770   }; //class Suurballe
   771 
   772   ///@}
   773 
   774 } //namespace lemon
   775 
   776 #endif //LEMON_SUURBALLE_H