lemon/dinitz_sleator_tarjan.h
author ladanyi
Tue, 27 Nov 2007 16:26:58 +0000
changeset 2523 ceb7f3c704b7
parent 2519 a7376f7ed899
child 2527 10f3b3286e63
permissions -rw-r--r--
Fix warning when compiling with -Wall.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     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_DINITZ_SLEATOR_TARJAN_H
    20 #define LEMON_DINITZ_SLEATOR_TARJAN_H
    21 
    22 /// \file 
    23 /// \ingroup max_flow 
    24 /// \brief Implementation the dynamic tree data structure of Sleator
    25 /// and Tarjan.
    26 
    27 #include <lemon/graph_utils.h>
    28 #include <lemon/tolerance.h>
    29 #include <lemon/dynamic_tree.h>
    30 
    31 #include <vector>
    32 #include <limits>
    33 #include <fstream>
    34 
    35 
    36 namespace lemon {
    37 
    38   /// \brief Default traits class of DinitzSleatorTarjan class.
    39   ///
    40   /// Default traits class of DinitzSleatorTarjan class.
    41   /// \param _Graph Graph type.
    42   /// \param _CapacityMap Type of capacity map.
    43   template <typename _Graph, typename _CapacityMap>
    44   struct DinitzSleatorTarjanDefaultTraits {
    45 
    46     /// \brief The graph type the algorithm runs on. 
    47     typedef _Graph Graph;
    48 
    49     /// \brief The type of the map that stores the edge capacities.
    50     ///
    51     /// The type of the map that stores the edge capacities.
    52     /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
    53     typedef _CapacityMap CapacityMap;
    54 
    55     /// \brief The type of the length of the edges.
    56     typedef typename CapacityMap::Value Value;
    57 
    58     /// \brief The map type that stores the flow values.
    59     ///
    60     /// The map type that stores the flow values. 
    61     /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
    62     typedef typename Graph::template EdgeMap<Value> FlowMap;
    63 
    64     /// \brief Instantiates a FlowMap.
    65     ///
    66     /// This function instantiates a \ref FlowMap. 
    67     /// \param graph The graph, to which we would like to define the flow map.
    68     static FlowMap* createFlowMap(const Graph& graph) {
    69       return new FlowMap(graph);
    70     }
    71 
    72     /// \brief The tolerance used by the algorithm
    73     ///
    74     /// The tolerance used by the algorithm to handle inexact computation.
    75     typedef Tolerance<Value> Tolerance;
    76 
    77   };
    78 
    79   /// \ingroup max_flow
    80   ///
    81   /// \brief Dinitz-Sleator-Tarjan algorithms class.
    82   ///
    83   /// This class provides an implementation of the \e
    84   /// Dinitz-Sleator-Tarjan \e algorithm producing a flow of maximum
    85   /// value in a directed graph. The DinitzSleatorTarjan algorithm is
    86   /// the fastest known max flow algorithms wich using blocking
    87   /// flow. It is an improvement of the Dinitz algorithm by using the
    88   /// \ref DynamicTree "dynamic tree" data structure of Sleator and
    89   /// Tarjan.
    90   ///
    91   /// This blocking flow algorithms builds a layered graph according
    92   /// to \ref Bfs "breadth-first search" distance from the target node
    93   /// in the reversed residual graph. The layered graph contains each
    94   /// residual edge which steps one level down. After that the
    95   /// algorithm constructs a blocking flow on the layered graph and
    96   /// augments the overall flow with it. The number of the levels in
    97   /// the layered graph is strictly increasing in each augmenting
    98   /// phase therefore the number of the augmentings is at most
    99   /// \f$n-1\f$.  The length of each phase is at most
   100   /// \f$O(m\log(n))\f$, that the overall time complexity is
   101   /// \f$O(nm\log(n))\f$.
   102   ///
   103   /// \param _Graph The directed graph type the algorithm runs on.
   104   /// \param _CapacityMap The capacity map type.
   105   /// \param _Traits Traits class to set various data types used by
   106   /// the algorithm.  The default traits class is \ref
   107   /// DinitzSleatorTarjanDefaultTraits.  See \ref
   108   /// DinitzSleatorTarjanDefaultTraits for the documentation of a
   109   /// Dinitz-Sleator-Tarjan traits class.
   110   ///
   111   /// \author Tamas Hamori and Balazs Dezso
   112 #ifdef DOXYGEN
   113   template <typename _Graph, typename _CapacityMap, typename _Traits>
   114 #else
   115   template <typename _Graph, 
   116 	    typename _CapacityMap = typename _Graph::template EdgeMap<int>,
   117 	    typename _Traits = 
   118 	    DinitzSleatorTarjanDefaultTraits<_Graph, _CapacityMap> >
   119 #endif
   120   class DinitzSleatorTarjan {
   121   public:
   122 
   123     typedef _Traits Traits;
   124     typedef typename Traits::Graph Graph;
   125     typedef typename Traits::CapacityMap CapacityMap;
   126     typedef typename Traits::Value Value; 
   127 
   128     typedef typename Traits::FlowMap FlowMap;
   129     typedef typename Traits::Tolerance Tolerance;
   130 
   131 
   132   private:
   133 
   134     GRAPH_TYPEDEFS(typename Graph);
   135 
   136 
   137     typedef typename Graph::template NodeMap<int> LevelMap;
   138     typedef typename Graph::template NodeMap<int> IntNodeMap;
   139     typedef typename Graph::template NodeMap<Edge> EdgeNodeMap;
   140     typedef DynamicTree<Value, IntNodeMap, Tolerance, false> DynTree;
   141 
   142   private:
   143     
   144     const Graph& _graph;
   145     const CapacityMap* _capacity;
   146 
   147     Node _source, _target;
   148 
   149     FlowMap* _flow;
   150     bool _local_flow;
   151 
   152     IntNodeMap* _level;
   153     EdgeNodeMap* _dt_edges;
   154     
   155     IntNodeMap* _dt_index;
   156     DynTree* _dt;
   157 
   158     std::vector<Node> _queue;
   159 
   160     Tolerance _tolerance;
   161     
   162     Value _flow_value;
   163     Value _max_value;
   164 
   165 
   166   public:
   167 
   168     typedef DinitzSleatorTarjan Create;
   169 
   170     ///\name Named template parameters
   171 
   172     ///@{
   173 
   174     template <typename _FlowMap>
   175     struct DefFlowMapTraits : public Traits {
   176       typedef _FlowMap FlowMap;
   177       static FlowMap *createFlowMap(const Graph&) {
   178 	throw UninitializedParameter();
   179       }
   180     };
   181 
   182     /// \brief \ref named-templ-param "Named parameter" for setting
   183     /// FlowMap type
   184     ///
   185     /// \ref named-templ-param "Named parameter" for setting FlowMap
   186     /// type
   187     template <typename _FlowMap>
   188     struct DefFlowMap 
   189       : public DinitzSleatorTarjan<Graph, CapacityMap, 
   190 			      DefFlowMapTraits<_FlowMap> > {
   191       typedef DinitzSleatorTarjan<Graph, CapacityMap, 
   192 			     DefFlowMapTraits<_FlowMap> > Create;
   193     };
   194 
   195     template <typename _Elevator>
   196     struct DefElevatorTraits : public Traits {
   197       typedef _Elevator Elevator;
   198       static Elevator *createElevator(const Graph&, int) {
   199 	throw UninitializedParameter();
   200       }
   201     };
   202 
   203     /// @}
   204 
   205     /// \brief \ref Exception for the case when the source equals the target.
   206     ///
   207     /// \ref Exception for the case when the source equals the target.
   208     ///
   209     class InvalidArgument : public lemon::LogicError {
   210     public:
   211       virtual const char* what() const throw() {
   212 	return "lemon::DinitzSleatorTarjan::InvalidArgument";
   213       }
   214     };
   215 
   216     /// \brief The constructor of the class.
   217     ///
   218     /// The constructor of the class. 
   219     /// \param graph The directed graph the algorithm runs on. 
   220     /// \param capacity The capacity of the edges. 
   221     /// \param source The source node.
   222     /// \param target The target node.
   223     DinitzSleatorTarjan(const Graph& graph, const CapacityMap& capacity,
   224 			Node source, Node target)
   225       : _graph(graph), _capacity(&capacity),
   226 	_source(source), _target(target),
   227 	_flow(0), _local_flow(false),
   228 	_level(0), _dt_edges(0),
   229 	_dt_index(0), _dt(0), _queue(),
   230 	_tolerance(), _flow_value(), _max_value()
   231     {
   232       if (_source == _target) {
   233 	throw InvalidArgument();
   234       }
   235     }
   236 
   237     /// \brief Destrcutor.
   238     ///
   239     /// Destructor.
   240     ~DinitzSleatorTarjan() {
   241       destroyStructures();
   242     }
   243 
   244     /// \brief Sets the capacity map.
   245     ///
   246     /// Sets the capacity map.
   247     /// \return \c (*this)
   248     DinitzSleatorTarjan& capacityMap(const CapacityMap& map) {
   249       _capacity = &map;
   250       return *this;
   251     }
   252 
   253     /// \brief Sets the flow map.
   254     ///
   255     /// Sets the flow map.
   256     /// \return \c (*this)
   257     DinitzSleatorTarjan& flowMap(FlowMap& map) {
   258       if (_local_flow) {
   259 	delete _flow;
   260 	_local_flow = false;
   261       }
   262       _flow = &map;
   263       return *this;
   264     }
   265 
   266     /// \brief Returns the flow map.
   267     ///
   268     /// \return The flow map.
   269     const FlowMap& flowMap() {
   270       return *_flow;
   271     }
   272 
   273     /// \brief Sets the source node.
   274     ///
   275     /// Sets the source node.
   276     /// \return \c (*this)
   277     DinitzSleatorTarjan& source(const Node& node) {
   278       _source = node;
   279       return *this;
   280     }
   281 
   282     /// \brief Sets the target node.
   283     ///
   284     /// Sets the target node.
   285     /// \return \c (*this)
   286     DinitzSleatorTarjan& target(const Node& node) {
   287       _target = node;
   288       return *this;
   289     }
   290 
   291     /// \brief Sets the tolerance used by algorithm.
   292     ///
   293     /// Sets the tolerance used by algorithm.
   294     DinitzSleatorTarjan& tolerance(const Tolerance& tolerance) const {
   295       _tolerance = tolerance;
   296       if (_dt) {
   297 	_dt.tolerance(_tolerance);
   298       }
   299       return *this;
   300     } 
   301 
   302     /// \brief Returns the tolerance used by algorithm.
   303     ///
   304     /// Returns the tolerance used by algorithm.
   305     const Tolerance& tolerance() const {
   306       return tolerance;
   307     } 
   308 
   309   private:
   310         
   311     void createStructures() {
   312       if (!_flow) {
   313 	_flow = Traits::createFlowMap(_graph);
   314 	_local_flow = true;
   315       }
   316       if (!_level) {
   317 	_level = new LevelMap(_graph);
   318       }
   319       if (!_dt_index && !_dt) {
   320 	_dt_index = new IntNodeMap(_graph);
   321 	_dt = new DynTree(*_dt_index, _tolerance);
   322       }
   323       if (!_dt_edges) {
   324 	_dt_edges = new EdgeNodeMap(_graph);
   325       }
   326       _queue.resize(countNodes(_graph));
   327       _max_value = _dt->maxValue();
   328     }
   329 
   330     void destroyStructures() {
   331       if (_local_flow) {
   332 	delete _flow;
   333       }
   334       if (_level) {
   335 	delete _level;
   336       }
   337       if (_dt) {
   338 	delete _dt;
   339       }
   340       if (_dt_index) {
   341 	delete _dt_index;
   342       }
   343       if (_dt_edges) {
   344 	delete _dt_edges;
   345       }
   346     }
   347 
   348     bool createLayeredGraph() {
   349 
   350       for (NodeIt n(_graph); n != INVALID; ++n) {
   351 	_level->set(n, -2);
   352       }
   353       
   354       int level = 0;
   355 
   356       _queue[0] = _target;
   357       _level->set(_target, level);
   358 
   359       int first = 0, last = 1, limit = 0;
   360       
   361       while (first != last && (*_level)[_source] == -2) {
   362 	if (first == limit) {
   363 	  limit = last;
   364 	  ++level;
   365 	}
   366 	
   367 	Node n = _queue[first++];
   368 	  
   369 	for (OutEdgeIt e(_graph, n); e != INVALID; ++e) {
   370 	  Node v = _graph.target(e);
   371 	  if ((*_level)[v] != -2) continue;
   372 	  Value rem = (*_flow)[e];
   373 	  if (!_tolerance.positive(rem)) continue;
   374 	  _level->set(v, level);
   375 	  _queue[last++] = v;
   376 	}
   377 	
   378 	for (InEdgeIt e(_graph, n); e != INVALID; ++e) {
   379 	  Node v = _graph.source(e);
   380 	  if ((*_level)[v] != -2) continue;
   381 	  Value rem = (*_capacity)[e] - (*_flow)[e];
   382 	  if (!_tolerance.positive(rem)) continue;
   383 	  _level->set(v, level);
   384 	  _queue[last++] = v;
   385 	}
   386       }
   387       return (*_level)[_source] != -2;
   388     }
   389 
   390     void initEdges() {
   391       for (NodeIt n(_graph); n != INVALID; ++n) {
   392 	_graph.firstOut((*_dt_edges)[n], n);
   393       }
   394     }
   395         
   396     
   397     void augmentPath() {
   398       Value rem;
   399       Node n = _dt->findCost(_source, rem);
   400       _flow_value += rem;
   401       _dt->addCost(_source, - rem);
   402 
   403       _dt->cut(n);
   404       _dt->addCost(n, _max_value);
   405 
   406       Edge e = (*_dt_edges)[n];
   407       if (_graph.source(e) == n) {
   408 	_flow->set(e, (*_capacity)[e]);
   409 	
   410 	_graph.nextOut(e);
   411 	if (e == INVALID) {
   412 	  _graph.firstIn(e, n);
   413 	}
   414       } else {
   415 	_flow->set(e, 0);
   416 	_graph.nextIn(e);
   417       }
   418       _dt_edges->set(n, e);
   419 
   420     }
   421 
   422     bool advance(Node n) {
   423       Edge e = (*_dt_edges)[n];
   424       if (e == INVALID) return false;
   425 
   426       Node u;
   427       Value rem;      
   428       if (_graph.source(e) == n) {
   429 	u = _graph.target(e);
   430 	while ((*_level)[n] != (*_level)[u] + 1 || 
   431 	       !_tolerance.positive((*_capacity)[e] - (*_flow)[e])) {
   432 	  _graph.nextOut(e);
   433 	  if (e == INVALID) break;
   434 	  u = _graph.target(e);
   435 	}
   436 	if (e != INVALID) {
   437 	  rem = (*_capacity)[e] - (*_flow)[e];
   438 	} else {
   439 	  _graph.firstIn(e, n);
   440 	  if (e == INVALID) {
   441 	    _dt_edges->set(n, INVALID);
   442 	    return false;
   443 	  }
   444 	  u = _graph.source(e);
   445 	  while ((*_level)[n] != (*_level)[u] + 1 ||
   446 		 !_tolerance.positive((*_flow)[e])) {
   447 	    _graph.nextIn(e);
   448 	    if (e == INVALID) {
   449 	      _dt_edges->set(n, INVALID);
   450 	      return false;
   451 	    }
   452 	    u = _graph.source(e);
   453 	  }
   454 	  rem = (*_flow)[e];
   455 	}
   456       } else {
   457 	u = _graph.source(e);
   458 	while ((*_level)[n] != (*_level)[u] + 1 ||
   459 	       !_tolerance.positive((*_flow)[e])) {
   460 	  _graph.nextIn(e);
   461 	  if (e == INVALID) {
   462 	    _dt_edges->set(n, INVALID);
   463 	    return false;
   464 	  }
   465 	  u = _graph.source(e);
   466 	}
   467 	rem = (*_flow)[e];
   468       }
   469 
   470       _dt->addCost(n, - std::numeric_limits<Value>::max());
   471       _dt->addCost(n, rem);
   472       _dt->link(n, u);
   473       _dt_edges->set(n, e);
   474       return true;
   475     }
   476 
   477     void retreat(Node n) {
   478       _level->set(n, -1);
   479       
   480       for (OutEdgeIt e(_graph, n); e != INVALID; ++e) {
   481 	Node u = _graph.target(e);
   482 	if ((*_dt_edges)[u] == e && _dt->findRoot(u) == n) {
   483 	  Value rem;
   484 	  _dt->findCost(u, rem);
   485 	  _flow->set(e, rem);
   486 	  _dt->cut(u);
   487 	  _dt->addCost(u, - rem);
   488 	  _dt->addCost(u, _max_value);
   489 	}
   490       }
   491       for (InEdgeIt e(_graph, n); e != INVALID; ++e) {
   492 	Node u = _graph.source(e);
   493 	if ((*_dt_edges)[u] == e && _dt->findRoot(u) == n) {
   494 	  Value rem;
   495 	  _dt->findCost(u, rem);
   496 	  _flow->set(e, (*_capacity)[e] - rem);
   497 	  _dt->cut(u);
   498 	  _dt->addCost(u, - rem);
   499 	  _dt->addCost(u, _max_value);
   500 	}
   501       }
   502     }
   503 
   504     void extractTrees() {
   505       for (NodeIt n(_graph); n != INVALID; ++n) {
   506 	
   507 	Node w = _dt->findRoot(n);
   508       
   509 	while (w != n) {
   510       
   511 	  Value rem;      
   512 	  Node u = _dt->findCost(n, rem);
   513 
   514 	  _dt->cut(u);
   515 	  _dt->addCost(u, - rem);
   516 	  _dt->addCost(u, _max_value);
   517 	  
   518 	  Edge e = (*_dt_edges)[u];
   519 	  _dt_edges->set(u, INVALID);
   520 	  
   521 	  if (u == _graph.source(e)) {
   522 	    _flow->set(e, (*_capacity)[e] - rem);
   523 	  } else {
   524 	    _flow->set(e, rem);
   525 	  }
   526 	  
   527 	  w = _dt->findRoot(n);
   528 	}      
   529       }
   530     }
   531 
   532 
   533   public:
   534     
   535     /// \name Execution control The simplest way to execute the
   536     /// algorithm is to use the \c run() member functions.
   537     /// \n
   538     /// If you need more control on initial solution or
   539     /// execution then you have to call one \ref init() function and then
   540     /// the start() or multiple times the \c augment() member function.  
   541     
   542     ///@{
   543 
   544     /// \brief Initializes the algorithm
   545     /// 
   546     /// It sets the flow to empty flow.
   547     void init() {
   548       createStructures();
   549 
   550       _dt->clear();
   551       for (NodeIt n(_graph); n != INVALID; ++n) {
   552         _dt->makeTree(n);
   553         _dt->addCost(n, _max_value);
   554       }
   555 
   556       for (EdgeIt it(_graph); it != INVALID; ++it) {
   557         _flow->set(it, 0);
   558       }
   559       _flow_value = 0;
   560     }
   561     
   562     /// \brief Initializes the algorithm
   563     /// 
   564     /// Initializes the flow to the \c flowMap. The \c flowMap should
   565     /// contain a feasible flow, ie. in each node excluding the source
   566     /// and the target the incoming flow should be equal to the
   567     /// outgoing flow.
   568     template <typename FlowMap>
   569     void flowInit(const FlowMap& flowMap) {
   570       createStructures();
   571 
   572       _dt->clear();
   573       for (NodeIt n(_graph); n != INVALID; ++n) {
   574         _dt->makeTree(n);
   575         _dt->addCost(n, _max_value);
   576       }
   577 
   578       for (EdgeIt e(_graph); e != INVALID; ++e) {
   579 	_flow->set(e, flowMap[e]);
   580       }
   581       _flow_value = 0;
   582       for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
   583         _flow_value += (*_flow)[jt];
   584       }
   585       for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
   586         _flow_value -= (*_flow)[jt];
   587       }
   588     }
   589 
   590     /// \brief Initializes the algorithm
   591     /// 
   592     /// Initializes the flow to the \c flowMap. The \c flowMap should
   593     /// contain a feasible flow, ie. in each node excluding the source
   594     /// and the target the incoming flow should be equal to the
   595     /// outgoing flow.  
   596     /// \return %False when the given flowMap does not contain
   597     /// feasible flow.
   598     template <typename FlowMap>
   599     bool checkedFlowInit(const FlowMap& flowMap) {
   600       createStructures();
   601 
   602       _dt->clear();
   603       for (NodeIt n(_graph); n != INVALID; ++n) {
   604         _dt->makeTree(n);
   605         _dt->addCost(n, _max_value);
   606       }
   607 
   608       for (EdgeIt e(_graph); e != INVALID; ++e) {
   609 	_flow->set(e, flowMap[e]);
   610       }
   611       for (NodeIt it(_graph); it != INVALID; ++it) {
   612         if (it == _source || it == _target) continue;
   613         Value outFlow = 0;
   614         for (OutEdgeIt jt(_graph, it); jt != INVALID; ++jt) {
   615           outFlow += (*_flow)[jt];
   616         }
   617         Value inFlow = 0;
   618         for (InEdgeIt jt(_graph, it); jt != INVALID; ++jt) {
   619           inFlow += (*_flow)[jt];
   620         }
   621         if (_tolerance.different(outFlow, inFlow)) {
   622           return false;
   623         }
   624       }
   625       for (EdgeIt it(_graph); it != INVALID; ++it) {
   626         if (_tolerance.less((*_flow)[it], 0)) return false;
   627         if (_tolerance.less((*_capacity)[it], (*_flow)[it])) return false;
   628       }
   629       _flow_value = 0;
   630       for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
   631         _flow_value += (*_flow)[jt];
   632       }
   633       for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
   634         _flow_value -= (*_flow)[jt];
   635       }
   636       return true;
   637     }
   638 
   639     /// \brief Executes the algorithm
   640     ///
   641     /// It runs augmenting phases by adding blocking flow until the
   642     /// optimal solution is reached.
   643     void start() {
   644       while (augment());
   645     }
   646 
   647     /// \brief Augments the flow with a blocking flow on a layered
   648     /// graph.
   649     /// 
   650     /// This function builds a layered graph and then find a blocking
   651     /// flow on this graph. The number of the levels in the layered
   652     /// graph is strictly increasing in each augmenting phase
   653     /// therefore the number of the augmentings is at most \f$ n-1
   654     /// \f$.  The length of each phase is at most \f$ O(m \log(n))
   655     /// \f$, that the overall time complexity is \f$ O(nm \log(n)) \f$.
   656     /// \return %False when there is not residual path between the
   657     /// source and the target so the current flow is a feasible and
   658     /// optimal solution.
   659     bool augment() {
   660       Node n;
   661 
   662       if (createLayeredGraph()) {
   663 	
   664 	Timer bf_timer;
   665 	initEdges();
   666 
   667 	n = _dt->findRoot(_source);
   668 	while (true) {
   669 	  Edge e;
   670 	  if (n == _target) {
   671 	    augmentPath();
   672 	  } else if (!advance(n)) {
   673 	    if (n != _source) {
   674 	      retreat(n);
   675 	    } else {
   676 	      break;
   677 	    }
   678 	  }
   679 	  n = _dt->findRoot(_source);
   680 	}     
   681 	extractTrees();
   682 
   683 	return true;
   684       } else {
   685 	return false;
   686       }
   687     }
   688     
   689     /// \brief runs the algorithm.
   690     /// 
   691     /// It is just a shorthand for:
   692     ///
   693     ///\code 
   694     /// ek.init();
   695     /// ek.start();
   696     ///\endcode
   697     void run() {
   698       init();
   699       start();
   700     }
   701 
   702     /// @}
   703 
   704     /// \name Query Functions 
   705     /// The result of the Dinitz-Sleator-Tarjan algorithm can be
   706     /// obtained using these functions.
   707     /// \n
   708     /// Before the use of these functions,
   709     /// either run() or start() must be called.
   710     
   711     ///@{
   712 
   713     /// \brief Returns the value of the maximum flow.
   714     ///
   715     /// Returns the value of the maximum flow by returning the excess
   716     /// of the target node \c t. This value equals to the value of
   717     /// the maximum flow already after the first phase.
   718     Value flowValue() const {
   719       return _flow_value;
   720     }
   721 
   722 
   723     /// \brief Returns the flow on the edge.
   724     ///
   725     /// Sets the \c flowMap to the flow on the edges. This method can
   726     /// be called after the second phase of algorithm.
   727     Value flow(const Edge& edge) const {
   728       return (*_flow)[edge];
   729     }
   730 
   731     /// \brief Returns true when the node is on the source side of minimum cut.
   732     ///
   733 
   734     /// Returns true when the node is on the source side of minimum
   735     /// cut. This method can be called both after running \ref
   736     /// startFirstPhase() and \ref startSecondPhase().
   737     bool minCut(const Node& node) const {
   738       return (*_level)[node] == -2;
   739     }
   740 
   741     /// \brief Returns a minimum value cut.
   742     ///
   743     /// Sets \c cut to the characteristic vector of a minimum value cut
   744     /// It simply calls the minMinCut member.
   745     /// \retval cut Write node bool map. 
   746     template <typename CutMap>
   747     void minCutMap(CutMap& cutMap) const {
   748       for (NodeIt n(_graph); n != INVALID; ++n) {
   749 	cutMap.set(n, (*_level)[n] == -2);
   750       }
   751       cutMap.set(_source, true);
   752     }    
   753 
   754     /// @}
   755 
   756   };
   757 }
   758 
   759 #endif