deba@2514: /* -*- C++ -*- deba@2514: * deba@2514: * This file is a part of LEMON, a generic C++ optimization library deba@2514: * deba@2514: * Copyright (C) 2003-2007 deba@2514: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@2514: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@2514: * deba@2514: * Permission to use, modify and distribute this software is granted deba@2514: * provided that this copyright notice appears in all copies. For deba@2514: * precise terms see the accompanying LICENSE file. deba@2514: * deba@2514: * This software is provided "AS IS" with no warranty of any kind, deba@2514: * express or implied, and with no claim as to its suitability for any deba@2514: * purpose. deba@2514: * deba@2514: */ deba@2514: deba@2514: #ifndef LEMON_DINITZ_SLEATOR_TARJAN_H deba@2514: #define LEMON_DINITZ_SLEATOR_TARJAN_H deba@2514: deba@2514: /// \file deba@2514: /// \ingroup max_flow deba@2514: /// \brief Implementation the dynamic tree data structure of Sleator deba@2514: /// and Tarjan. deba@2514: deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: deba@2514: deba@2514: namespace lemon { deba@2514: deba@2514: /// \brief Default traits class of DinitzSleatorTarjan class. deba@2514: /// deba@2514: /// Default traits class of DinitzSleatorTarjan class. deba@2514: /// \param _Graph Graph type. deba@2514: /// \param _CapacityMap Type of capacity map. deba@2514: template deba@2514: struct DinitzSleatorTarjanDefaultTraits { deba@2514: deba@2514: /// \brief The graph type the algorithm runs on. deba@2514: typedef _Graph Graph; deba@2514: deba@2514: /// \brief The type of the map that stores the edge capacities. deba@2514: /// deba@2514: /// The type of the map that stores the edge capacities. deba@2514: /// It must meet the \ref concepts::ReadMap "ReadMap" concept. deba@2514: typedef _CapacityMap CapacityMap; deba@2514: deba@2514: /// \brief The type of the length of the edges. deba@2514: typedef typename CapacityMap::Value Value; deba@2514: deba@2514: /// \brief The map type that stores the flow values. deba@2514: /// deba@2514: /// The map type that stores the flow values. deba@2514: /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. deba@2514: typedef typename Graph::template EdgeMap FlowMap; deba@2514: deba@2514: /// \brief Instantiates a FlowMap. deba@2514: /// deba@2514: /// This function instantiates a \ref FlowMap. deba@2514: /// \param graph The graph, to which we would like to define the flow map. deba@2514: static FlowMap* createFlowMap(const Graph& graph) { deba@2514: return new FlowMap(graph); deba@2514: } deba@2514: deba@2514: /// \brief The tolerance used by the algorithm deba@2514: /// deba@2514: /// The tolerance used by the algorithm to handle inexact computation. deba@2514: typedef Tolerance Tolerance; deba@2514: deba@2514: }; deba@2514: deba@2514: /// \ingroup max_flow deba@2514: /// deba@2514: /// \brief Dinitz-Sleator-Tarjan algorithms class. deba@2514: /// deba@2514: /// This class provides an implementation of the \e deba@2514: /// Dinitz-Sleator-Tarjan \e algorithm producing a flow of maximum deba@2514: /// value in a directed graph. The DinitzSleatorTarjan algorithm is deba@2514: /// the fastest known max flow algorithms wich using blocking deba@2514: /// flow. It is an improvement of the Dinitz algorithm by using the deba@2514: /// \ref DynamicTree "dynamic tree" data structure of Sleator and deba@2514: /// Tarjan. deba@2514: /// deba@2514: /// This blocking flow algorithms builds a layered graph according deba@2514: /// to \ref Bfs "breadth-first search" distance from the target node deba@2514: /// in the reversed residual graph. The layered graph contains each deba@2514: /// residual edge which steps one level down. After that the deba@2514: /// algorithm constructs a blocking flow on the layered graph and deba@2514: /// augments the overall flow with it. The number of the levels in deba@2514: /// the layered graph is strictly increasing in each augmenting deba@2514: /// phase therefore the number of the augmentings is at most deba@2514: /// \f$n-1\f$. The length of each phase is at most deba@2514: /// \f$O(m\log(n))\f$, that the overall time complexity is deba@2514: /// \f$O(nm\log(n))\f$. deba@2514: /// deba@2514: /// \param _Graph The directed graph type the algorithm runs on. deba@2514: /// \param _CapacityMap The capacity map type. deba@2514: /// \param _Traits Traits class to set various data types used by deba@2514: /// the algorithm. The default traits class is \ref deba@2514: /// DinitzSleatorTarjanDefaultTraits. See \ref deba@2514: /// DinitzSleatorTarjanDefaultTraits for the documentation of a deba@2514: /// Dinitz-Sleator-Tarjan traits class. deba@2514: /// deba@2514: /// \author Tamas Hamori and Balazs Dezso deba@2514: #ifdef DOXYGEN deba@2514: template deba@2514: #else deba@2514: template , deba@2514: typename _Traits = deba@2514: DinitzSleatorTarjanDefaultTraits<_Graph, _CapacityMap> > deba@2514: #endif deba@2514: class DinitzSleatorTarjan { deba@2514: public: deba@2514: deba@2514: typedef _Traits Traits; deba@2514: typedef typename Traits::Graph Graph; deba@2514: typedef typename Traits::CapacityMap CapacityMap; deba@2514: typedef typename Traits::Value Value; deba@2514: deba@2514: typedef typename Traits::FlowMap FlowMap; deba@2514: typedef typename Traits::Tolerance Tolerance; deba@2514: deba@2514: deba@2514: private: deba@2514: deba@2514: GRAPH_TYPEDEFS(typename Graph); deba@2514: deba@2514: deba@2514: typedef typename Graph::template NodeMap LevelMap; deba@2514: typedef typename Graph::template NodeMap IntNodeMap; deba@2514: typedef typename Graph::template NodeMap EdgeNodeMap; deba@2514: typedef DynamicTree DynTree; deba@2514: deba@2514: private: deba@2514: deba@2514: const Graph& _graph; deba@2514: const CapacityMap* _capacity; deba@2514: deba@2514: Node _source, _target; deba@2514: deba@2514: FlowMap* _flow; deba@2514: bool _local_flow; deba@2514: deba@2514: IntNodeMap* _level; deba@2514: EdgeNodeMap* _dt_edges; deba@2514: deba@2514: IntNodeMap* _dt_index; deba@2514: DynTree* _dt; deba@2514: deba@2519: std::vector _queue; deba@2519: deba@2514: Tolerance _tolerance; deba@2514: deba@2514: Value _flow_value; deba@2514: Value _max_value; deba@2514: deba@2514: deba@2514: public: deba@2514: deba@2514: typedef DinitzSleatorTarjan Create; deba@2514: deba@2514: ///\name Named template parameters deba@2514: deba@2514: ///@{ deba@2514: deba@2514: template deba@2514: struct DefFlowMapTraits : public Traits { deba@2514: typedef _FlowMap FlowMap; deba@2514: static FlowMap *createFlowMap(const Graph&) { deba@2514: throw UninitializedParameter(); deba@2514: } deba@2514: }; deba@2514: deba@2514: /// \brief \ref named-templ-param "Named parameter" for setting deba@2514: /// FlowMap type deba@2514: /// deba@2514: /// \ref named-templ-param "Named parameter" for setting FlowMap deba@2514: /// type deba@2514: template deba@2514: struct DefFlowMap deba@2514: : public DinitzSleatorTarjan > { deba@2514: typedef DinitzSleatorTarjan > Create; deba@2514: }; deba@2514: deba@2514: template deba@2514: struct DefElevatorTraits : public Traits { deba@2514: typedef _Elevator Elevator; deba@2514: static Elevator *createElevator(const Graph&, int) { deba@2514: throw UninitializedParameter(); deba@2514: } deba@2514: }; deba@2514: deba@2514: /// @} deba@2514: deba@2514: /// \brief \ref Exception for the case when the source equals the target. deba@2514: /// deba@2514: /// \ref Exception for the case when the source equals the target. deba@2514: /// deba@2514: class InvalidArgument : public lemon::LogicError { deba@2514: public: deba@2514: virtual const char* what() const throw() { deba@2514: return "lemon::DinitzSleatorTarjan::InvalidArgument"; deba@2514: } deba@2514: }; deba@2514: deba@2527: protected: deba@2527: deba@2527: DinitzSleatorTarjan() {} deba@2527: deba@2527: public: deba@2527: deba@2514: /// \brief The constructor of the class. deba@2514: /// deba@2514: /// The constructor of the class. deba@2514: /// \param graph The directed graph the algorithm runs on. deba@2514: /// \param capacity The capacity of the edges. deba@2514: /// \param source The source node. deba@2514: /// \param target The target node. deba@2514: DinitzSleatorTarjan(const Graph& graph, const CapacityMap& capacity, deba@2514: Node source, Node target) deba@2514: : _graph(graph), _capacity(&capacity), deba@2514: _source(source), _target(target), deba@2514: _flow(0), _local_flow(false), deba@2514: _level(0), _dt_edges(0), deba@2519: _dt_index(0), _dt(0), _queue(), deba@2514: _tolerance(), _flow_value(), _max_value() deba@2514: { deba@2514: if (_source == _target) { deba@2514: throw InvalidArgument(); deba@2514: } deba@2514: } deba@2514: deba@2514: /// \brief Destrcutor. deba@2514: /// deba@2514: /// Destructor. deba@2514: ~DinitzSleatorTarjan() { deba@2514: destroyStructures(); deba@2514: } deba@2514: deba@2514: /// \brief Sets the capacity map. deba@2514: /// deba@2514: /// Sets the capacity map. deba@2514: /// \return \c (*this) deba@2514: DinitzSleatorTarjan& capacityMap(const CapacityMap& map) { deba@2514: _capacity = ↦ deba@2514: return *this; deba@2514: } deba@2514: deba@2514: /// \brief Sets the flow map. deba@2514: /// deba@2514: /// Sets the flow map. deba@2514: /// \return \c (*this) deba@2514: DinitzSleatorTarjan& flowMap(FlowMap& map) { deba@2514: if (_local_flow) { deba@2514: delete _flow; deba@2514: _local_flow = false; deba@2514: } deba@2514: _flow = ↦ deba@2514: return *this; deba@2514: } deba@2514: deba@2514: /// \brief Returns the flow map. deba@2514: /// deba@2514: /// \return The flow map. deba@2514: const FlowMap& flowMap() { deba@2514: return *_flow; deba@2514: } deba@2514: deba@2514: /// \brief Sets the source node. deba@2514: /// deba@2514: /// Sets the source node. deba@2514: /// \return \c (*this) deba@2514: DinitzSleatorTarjan& source(const Node& node) { deba@2514: _source = node; deba@2514: return *this; deba@2514: } deba@2514: deba@2514: /// \brief Sets the target node. deba@2514: /// deba@2514: /// Sets the target node. deba@2514: /// \return \c (*this) deba@2514: DinitzSleatorTarjan& target(const Node& node) { deba@2514: _target = node; deba@2514: return *this; deba@2514: } deba@2514: deba@2514: /// \brief Sets the tolerance used by algorithm. deba@2514: /// deba@2514: /// Sets the tolerance used by algorithm. deba@2514: DinitzSleatorTarjan& tolerance(const Tolerance& tolerance) const { deba@2514: _tolerance = tolerance; deba@2514: if (_dt) { deba@2514: _dt.tolerance(_tolerance); deba@2514: } deba@2514: return *this; deba@2514: } deba@2514: deba@2514: /// \brief Returns the tolerance used by algorithm. deba@2514: /// deba@2514: /// Returns the tolerance used by algorithm. deba@2514: const Tolerance& tolerance() const { deba@2514: return tolerance; deba@2514: } deba@2514: deba@2514: private: deba@2514: deba@2514: void createStructures() { deba@2514: if (!_flow) { deba@2514: _flow = Traits::createFlowMap(_graph); deba@2514: _local_flow = true; deba@2514: } deba@2514: if (!_level) { deba@2514: _level = new LevelMap(_graph); deba@2514: } deba@2514: if (!_dt_index && !_dt) { deba@2514: _dt_index = new IntNodeMap(_graph); deba@2514: _dt = new DynTree(*_dt_index, _tolerance); deba@2514: } deba@2514: if (!_dt_edges) { deba@2514: _dt_edges = new EdgeNodeMap(_graph); deba@2514: } deba@2519: _queue.resize(countNodes(_graph)); deba@2514: _max_value = _dt->maxValue(); deba@2514: } deba@2514: deba@2514: void destroyStructures() { deba@2514: if (_local_flow) { deba@2514: delete _flow; deba@2514: } deba@2514: if (_level) { deba@2514: delete _level; deba@2514: } deba@2514: if (_dt) { deba@2514: delete _dt; deba@2514: } deba@2514: if (_dt_index) { deba@2514: delete _dt_index; deba@2514: } deba@2514: if (_dt_edges) { deba@2514: delete _dt_edges; deba@2514: } deba@2514: } deba@2514: deba@2514: bool createLayeredGraph() { deba@2514: deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: _level->set(n, -2); deba@2514: } deba@2514: deba@2514: int level = 0; deba@2514: deba@2519: _queue[0] = _target; deba@2514: _level->set(_target, level); deba@2519: deba@2519: int first = 0, last = 1, limit = 0; deba@2514: deba@2519: while (first != last && (*_level)[_source] == -2) { deba@2519: if (first == limit) { deba@2519: limit = last; deba@2519: ++level; deba@2519: } deba@2514: deba@2519: Node n = _queue[first++]; deba@2514: deba@2519: for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2519: Node v = _graph.target(e); deba@2519: if ((*_level)[v] != -2) continue; deba@2519: Value rem = (*_flow)[e]; deba@2519: if (!_tolerance.positive(rem)) continue; deba@2519: _level->set(v, level); deba@2519: _queue[last++] = v; deba@2514: } deba@2519: deba@2519: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2519: Node v = _graph.source(e); deba@2519: if ((*_level)[v] != -2) continue; deba@2519: Value rem = (*_capacity)[e] - (*_flow)[e]; deba@2519: if (!_tolerance.positive(rem)) continue; deba@2519: _level->set(v, level); deba@2519: _queue[last++] = v; deba@2519: } deba@2514: } deba@2514: return (*_level)[_source] != -2; deba@2514: } deba@2514: deba@2514: void initEdges() { deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: _graph.firstOut((*_dt_edges)[n], n); deba@2514: } deba@2514: } deba@2514: deba@2514: deba@2514: void augmentPath() { deba@2514: Value rem; deba@2514: Node n = _dt->findCost(_source, rem); deba@2514: _flow_value += rem; deba@2514: _dt->addCost(_source, - rem); deba@2514: deba@2514: _dt->cut(n); deba@2514: _dt->addCost(n, _max_value); deba@2514: deba@2514: Edge e = (*_dt_edges)[n]; deba@2514: if (_graph.source(e) == n) { deba@2514: _flow->set(e, (*_capacity)[e]); deba@2514: deba@2514: _graph.nextOut(e); deba@2514: if (e == INVALID) { deba@2514: _graph.firstIn(e, n); deba@2514: } deba@2514: } else { deba@2514: _flow->set(e, 0); deba@2514: _graph.nextIn(e); deba@2514: } deba@2514: _dt_edges->set(n, e); deba@2514: deba@2514: } deba@2514: deba@2514: bool advance(Node n) { deba@2514: Edge e = (*_dt_edges)[n]; deba@2514: if (e == INVALID) return false; deba@2514: deba@2514: Node u; deba@2514: Value rem; deba@2514: if (_graph.source(e) == n) { deba@2514: u = _graph.target(e); deba@2514: while ((*_level)[n] != (*_level)[u] + 1 || deba@2514: !_tolerance.positive((*_capacity)[e] - (*_flow)[e])) { deba@2514: _graph.nextOut(e); deba@2514: if (e == INVALID) break; deba@2514: u = _graph.target(e); deba@2514: } deba@2514: if (e != INVALID) { deba@2514: rem = (*_capacity)[e] - (*_flow)[e]; deba@2514: } else { deba@2514: _graph.firstIn(e, n); deba@2514: if (e == INVALID) { deba@2514: _dt_edges->set(n, INVALID); deba@2514: return false; deba@2514: } deba@2514: u = _graph.source(e); deba@2514: while ((*_level)[n] != (*_level)[u] + 1 || deba@2514: !_tolerance.positive((*_flow)[e])) { deba@2514: _graph.nextIn(e); deba@2514: if (e == INVALID) { deba@2514: _dt_edges->set(n, INVALID); deba@2514: return false; deba@2514: } deba@2514: u = _graph.source(e); deba@2514: } deba@2514: rem = (*_flow)[e]; deba@2514: } deba@2514: } else { deba@2514: u = _graph.source(e); deba@2514: while ((*_level)[n] != (*_level)[u] + 1 || deba@2514: !_tolerance.positive((*_flow)[e])) { deba@2514: _graph.nextIn(e); deba@2514: if (e == INVALID) { deba@2514: _dt_edges->set(n, INVALID); deba@2514: return false; deba@2514: } deba@2514: u = _graph.source(e); deba@2514: } deba@2514: rem = (*_flow)[e]; deba@2514: } deba@2514: deba@2514: _dt->addCost(n, - std::numeric_limits::max()); deba@2514: _dt->addCost(n, rem); deba@2514: _dt->link(n, u); deba@2514: _dt_edges->set(n, e); deba@2514: return true; deba@2514: } deba@2514: deba@2514: void retreat(Node n) { deba@2514: _level->set(n, -1); deba@2514: deba@2514: for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Node u = _graph.target(e); deba@2514: if ((*_dt_edges)[u] == e && _dt->findRoot(u) == n) { deba@2514: Value rem; deba@2514: _dt->findCost(u, rem); deba@2514: _flow->set(e, rem); deba@2514: _dt->cut(u); deba@2514: _dt->addCost(u, - rem); deba@2514: _dt->addCost(u, _max_value); deba@2514: } deba@2514: } deba@2514: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Node u = _graph.source(e); deba@2514: if ((*_dt_edges)[u] == e && _dt->findRoot(u) == n) { deba@2514: Value rem; deba@2514: _dt->findCost(u, rem); deba@2514: _flow->set(e, (*_capacity)[e] - rem); deba@2514: _dt->cut(u); deba@2514: _dt->addCost(u, - rem); deba@2514: _dt->addCost(u, _max_value); deba@2514: } deba@2514: } deba@2514: } deba@2514: deba@2514: void extractTrees() { deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: deba@2514: Node w = _dt->findRoot(n); deba@2514: deba@2514: while (w != n) { deba@2514: deba@2514: Value rem; deba@2514: Node u = _dt->findCost(n, rem); deba@2514: deba@2514: _dt->cut(u); deba@2514: _dt->addCost(u, - rem); deba@2514: _dt->addCost(u, _max_value); deba@2514: deba@2514: Edge e = (*_dt_edges)[u]; deba@2514: _dt_edges->set(u, INVALID); deba@2514: deba@2514: if (u == _graph.source(e)) { deba@2514: _flow->set(e, (*_capacity)[e] - rem); deba@2514: } else { deba@2514: _flow->set(e, rem); deba@2514: } deba@2514: deba@2514: w = _dt->findRoot(n); deba@2514: } deba@2514: } deba@2514: } deba@2514: deba@2514: deba@2514: public: deba@2514: deba@2514: /// \name Execution control The simplest way to execute the deba@2514: /// algorithm is to use the \c run() member functions. deba@2514: /// \n deba@2514: /// If you need more control on initial solution or deba@2514: /// execution then you have to call one \ref init() function and then deba@2514: /// the start() or multiple times the \c augment() member function. deba@2514: deba@2514: ///@{ deba@2514: deba@2514: /// \brief Initializes the algorithm deba@2514: /// deba@2514: /// It sets the flow to empty flow. deba@2514: void init() { deba@2514: createStructures(); deba@2514: deba@2514: _dt->clear(); deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: _dt->makeTree(n); deba@2514: _dt->addCost(n, _max_value); deba@2514: } deba@2514: deba@2514: for (EdgeIt it(_graph); it != INVALID; ++it) { deba@2514: _flow->set(it, 0); deba@2514: } deba@2514: _flow_value = 0; deba@2514: } deba@2514: deba@2514: /// \brief Initializes the algorithm deba@2514: /// deba@2514: /// Initializes the flow to the \c flowMap. The \c flowMap should deba@2514: /// contain a feasible flow, ie. in each node excluding the source deba@2514: /// and the target the incoming flow should be equal to the deba@2514: /// outgoing flow. deba@2514: template deba@2514: void flowInit(const FlowMap& flowMap) { deba@2514: createStructures(); deba@2514: deba@2514: _dt->clear(); deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: _dt->makeTree(n); deba@2514: _dt->addCost(n, _max_value); deba@2514: } deba@2514: deba@2514: for (EdgeIt e(_graph); e != INVALID; ++e) { deba@2514: _flow->set(e, flowMap[e]); deba@2514: } deba@2514: _flow_value = 0; deba@2514: for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) { deba@2514: _flow_value += (*_flow)[jt]; deba@2514: } deba@2514: for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) { deba@2514: _flow_value -= (*_flow)[jt]; deba@2514: } deba@2514: } deba@2514: deba@2514: /// \brief Initializes the algorithm deba@2514: /// deba@2514: /// Initializes the flow to the \c flowMap. The \c flowMap should deba@2514: /// contain a feasible flow, ie. in each node excluding the source deba@2514: /// and the target the incoming flow should be equal to the deba@2514: /// outgoing flow. deba@2514: /// \return %False when the given flowMap does not contain deba@2514: /// feasible flow. deba@2514: template deba@2514: bool checkedFlowInit(const FlowMap& flowMap) { deba@2514: createStructures(); deba@2514: deba@2514: _dt->clear(); deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: _dt->makeTree(n); deba@2514: _dt->addCost(n, _max_value); deba@2514: } deba@2514: deba@2514: for (EdgeIt e(_graph); e != INVALID; ++e) { deba@2514: _flow->set(e, flowMap[e]); deba@2514: } deba@2514: for (NodeIt it(_graph); it != INVALID; ++it) { deba@2514: if (it == _source || it == _target) continue; deba@2514: Value outFlow = 0; deba@2514: for (OutEdgeIt jt(_graph, it); jt != INVALID; ++jt) { deba@2514: outFlow += (*_flow)[jt]; deba@2514: } deba@2514: Value inFlow = 0; deba@2514: for (InEdgeIt jt(_graph, it); jt != INVALID; ++jt) { deba@2514: inFlow += (*_flow)[jt]; deba@2514: } deba@2514: if (_tolerance.different(outFlow, inFlow)) { deba@2514: return false; deba@2514: } deba@2514: } deba@2514: for (EdgeIt it(_graph); it != INVALID; ++it) { deba@2514: if (_tolerance.less((*_flow)[it], 0)) return false; deba@2514: if (_tolerance.less((*_capacity)[it], (*_flow)[it])) return false; deba@2514: } deba@2514: _flow_value = 0; deba@2514: for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) { deba@2514: _flow_value += (*_flow)[jt]; deba@2514: } deba@2514: for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) { deba@2514: _flow_value -= (*_flow)[jt]; deba@2514: } deba@2514: return true; deba@2514: } deba@2514: deba@2514: /// \brief Executes the algorithm deba@2514: /// deba@2514: /// It runs augmenting phases by adding blocking flow until the deba@2514: /// optimal solution is reached. deba@2514: void start() { deba@2514: while (augment()); deba@2514: } deba@2514: deba@2514: /// \brief Augments the flow with a blocking flow on a layered deba@2514: /// graph. deba@2514: /// deba@2514: /// This function builds a layered graph and then find a blocking deba@2514: /// flow on this graph. The number of the levels in the layered deba@2514: /// graph is strictly increasing in each augmenting phase deba@2514: /// therefore the number of the augmentings is at most \f$ n-1 deba@2514: /// \f$. The length of each phase is at most \f$ O(m \log(n)) deba@2514: /// \f$, that the overall time complexity is \f$ O(nm \log(n)) \f$. deba@2514: /// \return %False when there is not residual path between the deba@2514: /// source and the target so the current flow is a feasible and deba@2514: /// optimal solution. deba@2514: bool augment() { deba@2514: Node n; deba@2514: deba@2514: if (createLayeredGraph()) { deba@2514: deba@2514: Timer bf_timer; deba@2514: initEdges(); deba@2514: deba@2514: n = _dt->findRoot(_source); deba@2514: while (true) { deba@2514: Edge e; deba@2514: if (n == _target) { deba@2514: augmentPath(); deba@2514: } else if (!advance(n)) { deba@2514: if (n != _source) { deba@2514: retreat(n); deba@2514: } else { deba@2514: break; deba@2514: } deba@2514: } deba@2514: n = _dt->findRoot(_source); deba@2514: } deba@2514: extractTrees(); deba@2514: deba@2514: return true; deba@2514: } else { deba@2514: return false; deba@2514: } deba@2514: } deba@2514: deba@2514: /// \brief runs the algorithm. deba@2514: /// deba@2514: /// It is just a shorthand for: deba@2514: /// deba@2514: ///\code deba@2514: /// ek.init(); deba@2514: /// ek.start(); deba@2514: ///\endcode deba@2514: void run() { deba@2514: init(); deba@2514: start(); deba@2514: } deba@2514: deba@2514: /// @} deba@2514: deba@2522: /// \name Query Functions deba@2522: /// The result of the Dinitz-Sleator-Tarjan algorithm can be deba@2522: /// obtained using these functions. deba@2522: /// \n deba@2514: /// Before the use of these functions, deba@2514: /// either run() or start() must be called. deba@2514: deba@2514: ///@{ deba@2514: deba@2514: /// \brief Returns the value of the maximum flow. deba@2514: /// deba@2514: /// Returns the value of the maximum flow by returning the excess deba@2514: /// of the target node \c t. This value equals to the value of deba@2514: /// the maximum flow already after the first phase. deba@2514: Value flowValue() const { deba@2514: return _flow_value; deba@2514: } deba@2514: deba@2514: deba@2514: /// \brief Returns the flow on the edge. deba@2514: /// deba@2514: /// Sets the \c flowMap to the flow on the edges. This method can deba@2514: /// be called after the second phase of algorithm. deba@2514: Value flow(const Edge& edge) const { deba@2514: return (*_flow)[edge]; deba@2514: } deba@2514: deba@2514: /// \brief Returns true when the node is on the source side of minimum cut. deba@2514: /// deba@2514: deba@2514: /// Returns true when the node is on the source side of minimum deba@2514: /// cut. This method can be called both after running \ref deba@2514: /// startFirstPhase() and \ref startSecondPhase(). deba@2514: bool minCut(const Node& node) const { deba@2514: return (*_level)[node] == -2; deba@2514: } deba@2514: deba@2514: /// \brief Returns a minimum value cut. deba@2514: /// deba@2514: /// Sets \c cut to the characteristic vector of a minimum value cut deba@2514: /// It simply calls the minMinCut member. deba@2514: /// \retval cut Write node bool map. deba@2514: template deba@2514: void minCutMap(CutMap& cutMap) const { deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: cutMap.set(n, (*_level)[n] == -2); deba@2514: } deba@2514: cutMap.set(_source, true); deba@2514: } deba@2514: deba@2514: /// @} deba@2514: deba@2514: }; deba@2514: } deba@2514: deba@2514: #endif