alpar@404: /* -*- mode: C++; indent-tabs-mode: nil; -*- alpar@404: * alpar@404: * This file is a part of LEMON, a generic C++ optimization library. alpar@404: * alpar@404: * Copyright (C) 2003-2008 alpar@404: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@404: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@404: * alpar@404: * Permission to use, modify and distribute this software is granted alpar@404: * provided that this copyright notice appears in all copies. For alpar@404: * precise terms see the accompanying LICENSE file. alpar@404: * alpar@404: * This software is provided "AS IS" with no warranty of any kind, alpar@404: * express or implied, and with no claim as to its suitability for any alpar@404: * purpose. alpar@404: * alpar@404: */ alpar@404: alpar@404: #ifndef LEMON_PREFLOW_H alpar@404: #define LEMON_PREFLOW_H alpar@404: alpar@404: #include alpar@404: #include alpar@404: alpar@404: /// \file alpar@404: /// \ingroup max_flow alpar@404: /// \brief Implementation of the preflow algorithm. alpar@404: alpar@404: namespace lemon { alpar@404: alpar@404: /// \brief Default traits class of Preflow class. alpar@404: /// alpar@404: /// Default traits class of Preflow class. alpar@404: /// \param _Graph Digraph type. alpar@404: /// \param _CapacityMap Type of capacity map. alpar@404: template alpar@404: struct PreflowDefaultTraits { alpar@404: alpar@404: /// \brief The digraph type the algorithm runs on. alpar@404: typedef _Graph Digraph; alpar@404: alpar@404: /// \brief The type of the map that stores the arc capacities. alpar@404: /// alpar@404: /// The type of the map that stores the arc capacities. alpar@404: /// It must meet the \ref concepts::ReadMap "ReadMap" concept. alpar@404: typedef _CapacityMap CapacityMap; alpar@404: alpar@404: /// \brief The type of the length of the arcs. alpar@404: typedef typename CapacityMap::Value Value; alpar@404: alpar@404: /// \brief The map type that stores the flow values. alpar@404: /// alpar@404: /// The map type that stores the flow values. alpar@404: /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. alpar@404: typedef typename Digraph::template ArcMap FlowMap; alpar@404: alpar@404: /// \brief Instantiates a FlowMap. alpar@404: /// alpar@404: /// This function instantiates a \ref FlowMap. alpar@404: /// \param digraph The digraph, to which we would like to define alpar@404: /// the flow map. alpar@404: static FlowMap* createFlowMap(const Digraph& digraph) { alpar@404: return new FlowMap(digraph); alpar@404: } alpar@404: alpar@404: /// \brief The eleavator type used by Preflow algorithm. alpar@404: /// alpar@404: /// The elevator type used by Preflow algorithm. alpar@404: /// alpar@404: /// \sa Elevator alpar@404: /// \sa LinkedElevator alpar@404: typedef LinkedElevator Elevator; alpar@404: alpar@404: /// \brief Instantiates an Elevator. alpar@404: /// alpar@404: /// This function instantiates a \ref Elevator. alpar@404: /// \param digraph The digraph, to which we would like to define alpar@404: /// the elevator. alpar@404: /// \param max_level The maximum level of the elevator. alpar@404: static Elevator* createElevator(const Digraph& digraph, int max_level) { alpar@404: return new Elevator(digraph, max_level); alpar@404: } alpar@404: alpar@404: /// \brief The tolerance used by the algorithm alpar@404: /// alpar@404: /// The tolerance used by the algorithm to handle inexact computation. alpar@404: typedef lemon::Tolerance Tolerance; alpar@404: alpar@404: }; alpar@404: alpar@404: alpar@404: /// \ingroup max_flow alpar@404: /// alpar@404: /// \brief %Preflow algorithms class. alpar@404: /// alpar@404: /// This class provides an implementation of the Goldberg's \e alpar@404: /// preflow \e algorithm producing a flow of maximum value in a alpar@404: /// digraph. The preflow algorithms are the fastest known max alpar@404: /// flow algorithms. The current implementation use a mixture of the alpar@404: /// \e "highest label" and the \e "bound decrease" heuristics. alpar@404: /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{e})\f$. alpar@404: /// alpar@404: /// The algorithm consists from two phases. After the first phase alpar@404: /// the maximal flow value and the minimum cut can be obtained. The alpar@404: /// second phase constructs the feasible maximum flow on each arc. alpar@404: /// alpar@404: /// \param _Graph The digraph type the algorithm runs on. alpar@404: /// \param _CapacityMap The flow map type. alpar@404: /// \param _Traits Traits class to set various data types used by alpar@404: /// the algorithm. The default traits class is \ref alpar@404: /// PreflowDefaultTraits. See \ref PreflowDefaultTraits for the alpar@404: /// documentation of a %Preflow traits class. alpar@404: /// alpar@404: ///\author Jacint Szabo and Balazs Dezso alpar@404: #ifdef DOXYGEN alpar@404: template alpar@404: #else alpar@404: template , alpar@404: typename _Traits = PreflowDefaultTraits<_Graph, _CapacityMap> > alpar@404: #endif alpar@404: class Preflow { alpar@404: public: alpar@404: alpar@404: typedef _Traits Traits; alpar@404: typedef typename Traits::Digraph Digraph; alpar@404: typedef typename Traits::CapacityMap CapacityMap; alpar@404: typedef typename Traits::Value Value; alpar@404: alpar@404: typedef typename Traits::FlowMap FlowMap; alpar@404: typedef typename Traits::Elevator Elevator; alpar@404: typedef typename Traits::Tolerance Tolerance; alpar@404: alpar@404: private: alpar@404: alpar@404: TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); alpar@404: alpar@404: const Digraph& _graph; alpar@404: const CapacityMap* _capacity; alpar@404: alpar@404: int _node_num; alpar@404: alpar@404: Node _source, _target; alpar@404: alpar@404: FlowMap* _flow; alpar@404: bool _local_flow; alpar@404: alpar@404: Elevator* _level; alpar@404: bool _local_level; alpar@404: alpar@404: typedef typename Digraph::template NodeMap ExcessMap; alpar@404: ExcessMap* _excess; alpar@404: alpar@404: Tolerance _tolerance; alpar@404: alpar@404: bool _phase; alpar@404: alpar@404: alpar@404: void createStructures() { alpar@404: _node_num = countNodes(_graph); alpar@404: alpar@404: if (!_flow) { alpar@404: _flow = Traits::createFlowMap(_graph); alpar@404: _local_flow = true; alpar@404: } alpar@404: if (!_level) { alpar@404: _level = Traits::createElevator(_graph, _node_num); alpar@404: _local_level = true; alpar@404: } alpar@404: if (!_excess) { alpar@404: _excess = new ExcessMap(_graph); alpar@404: } alpar@404: } alpar@404: alpar@404: void destroyStructures() { alpar@404: if (_local_flow) { alpar@404: delete _flow; alpar@404: } alpar@404: if (_local_level) { alpar@404: delete _level; alpar@404: } alpar@404: if (_excess) { alpar@404: delete _excess; alpar@404: } alpar@404: } alpar@404: alpar@404: public: alpar@404: alpar@404: typedef Preflow Create; alpar@404: alpar@404: ///\name Named template parameters alpar@404: alpar@404: ///@{ alpar@404: alpar@404: template alpar@406: struct SetFlowMapTraits : public Traits { alpar@404: typedef _FlowMap FlowMap; alpar@404: static FlowMap *createFlowMap(const Digraph&) { alpar@405: LEMON_ASSERT(false, "FlowMap is not initialized"); alpar@405: return 0; // ignore warnings alpar@404: } alpar@404: }; alpar@404: alpar@404: /// \brief \ref named-templ-param "Named parameter" for setting alpar@404: /// FlowMap type alpar@404: /// alpar@404: /// \ref named-templ-param "Named parameter" for setting FlowMap alpar@404: /// type alpar@404: template alpar@406: struct SetFlowMap alpar@406: : public Preflow > { alpar@404: typedef Preflow > Create; alpar@404: }; alpar@404: alpar@404: template alpar@406: struct SetElevatorTraits : public Traits { alpar@404: typedef _Elevator Elevator; alpar@404: static Elevator *createElevator(const Digraph&, int) { alpar@405: LEMON_ASSERT(false, "Elevator is not initialized"); alpar@405: return 0; // ignore warnings alpar@404: } alpar@404: }; alpar@404: alpar@404: /// \brief \ref named-templ-param "Named parameter" for setting alpar@404: /// Elevator type alpar@404: /// alpar@404: /// \ref named-templ-param "Named parameter" for setting Elevator alpar@404: /// type alpar@404: template alpar@406: struct SetElevator alpar@406: : public Preflow > { alpar@404: typedef Preflow > Create; alpar@404: }; alpar@404: alpar@404: template alpar@406: struct SetStandardElevatorTraits : public Traits { alpar@404: typedef _Elevator Elevator; alpar@404: static Elevator *createElevator(const Digraph& digraph, int max_level) { alpar@404: return new Elevator(digraph, max_level); alpar@404: } alpar@404: }; alpar@404: alpar@404: /// \brief \ref named-templ-param "Named parameter" for setting alpar@404: /// Elevator type alpar@404: /// alpar@404: /// \ref named-templ-param "Named parameter" for setting Elevator alpar@404: /// type. The Elevator should be standard constructor interface, ie. alpar@404: /// the digraph and the maximum level should be passed to it. alpar@404: template alpar@406: struct SetStandardElevator alpar@404: : public Preflow > { alpar@404: typedef Preflow > Create; alpar@404: }; alpar@404: alpar@404: /// @} alpar@404: alpar@404: protected: alpar@404: alpar@404: Preflow() {} alpar@404: alpar@404: public: alpar@404: alpar@404: alpar@404: /// \brief The constructor of the class. alpar@404: /// alpar@404: /// The constructor of the class. alpar@404: /// \param digraph The digraph the algorithm runs on. alpar@404: /// \param capacity The capacity of the arcs. alpar@404: /// \param source The source node. alpar@404: /// \param target The target node. alpar@404: Preflow(const Digraph& digraph, const CapacityMap& capacity, alpar@404: Node source, Node target) alpar@404: : _graph(digraph), _capacity(&capacity), alpar@404: _node_num(0), _source(source), _target(target), alpar@404: _flow(0), _local_flow(false), alpar@404: _level(0), _local_level(false), alpar@404: _excess(0), _tolerance(), _phase() {} alpar@404: alpar@404: /// \brief Destrcutor. alpar@404: /// alpar@404: /// Destructor. alpar@404: ~Preflow() { alpar@404: destroyStructures(); alpar@404: } alpar@404: alpar@404: /// \brief Sets the capacity map. alpar@404: /// alpar@404: /// Sets the capacity map. alpar@404: /// \return \c (*this) alpar@404: Preflow& capacityMap(const CapacityMap& map) { alpar@404: _capacity = ↦ alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Sets the flow map. alpar@404: /// alpar@404: /// Sets the flow map. alpar@404: /// \return \c (*this) alpar@404: Preflow& flowMap(FlowMap& map) { alpar@404: if (_local_flow) { alpar@404: delete _flow; alpar@404: _local_flow = false; alpar@404: } alpar@404: _flow = ↦ alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Returns the flow map. alpar@404: /// alpar@404: /// \return The flow map. alpar@404: const FlowMap& flowMap() { alpar@404: return *_flow; alpar@404: } alpar@404: alpar@404: /// \brief Sets the elevator. alpar@404: /// alpar@404: /// Sets the elevator. alpar@404: /// \return \c (*this) alpar@404: Preflow& elevator(Elevator& elevator) { alpar@404: if (_local_level) { alpar@404: delete _level; alpar@404: _local_level = false; alpar@404: } alpar@404: _level = &elevator; alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Returns the elevator. alpar@404: /// alpar@404: /// \return The elevator. alpar@404: const Elevator& elevator() { alpar@404: return *_level; alpar@404: } alpar@404: alpar@404: /// \brief Sets the source node. alpar@404: /// alpar@404: /// Sets the source node. alpar@404: /// \return \c (*this) alpar@404: Preflow& source(const Node& node) { alpar@404: _source = node; alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Sets the target node. alpar@404: /// alpar@404: /// Sets the target node. alpar@404: /// \return \c (*this) alpar@404: Preflow& target(const Node& node) { alpar@404: _target = node; alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Sets the tolerance used by algorithm. alpar@404: /// alpar@404: /// Sets the tolerance used by algorithm. alpar@404: Preflow& tolerance(const Tolerance& tolerance) const { alpar@404: _tolerance = tolerance; alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Returns the tolerance used by algorithm. alpar@404: /// alpar@404: /// Returns the tolerance used by algorithm. alpar@404: const Tolerance& tolerance() const { alpar@404: return tolerance; alpar@404: } alpar@404: alpar@404: /// \name Execution control The simplest way to execute the alpar@404: /// algorithm is to use one of the member functions called \c alpar@404: /// run(). alpar@404: /// \n alpar@404: /// If you need more control on initial solution or alpar@404: /// execution then you have to call one \ref init() function and then alpar@404: /// the startFirstPhase() and if you need the startSecondPhase(). alpar@404: alpar@404: ///@{ alpar@404: alpar@404: /// \brief Initializes the internal data structures. alpar@404: /// alpar@404: /// Initializes the internal data structures. alpar@404: /// alpar@404: void init() { alpar@404: createStructures(); alpar@404: alpar@404: _phase = true; alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: _excess->set(n, 0); alpar@404: } alpar@404: alpar@404: for (ArcIt e(_graph); e != INVALID; ++e) { alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: alpar@404: typename Digraph::template NodeMap reached(_graph, false); alpar@404: alpar@404: _level->initStart(); alpar@404: _level->initAddItem(_target); alpar@404: alpar@404: std::vector queue; alpar@404: reached.set(_source, true); alpar@404: alpar@404: queue.push_back(_target); alpar@404: reached.set(_target, true); alpar@404: while (!queue.empty()) { alpar@404: _level->initNewLevel(); alpar@404: std::vector nqueue; alpar@404: for (int i = 0; i < int(queue.size()); ++i) { alpar@404: Node n = queue[i]; alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node u = _graph.source(e); alpar@404: if (!reached[u] && _tolerance.positive((*_capacity)[e])) { alpar@404: reached.set(u, true); alpar@404: _level->initAddItem(u); alpar@404: nqueue.push_back(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: queue.swap(nqueue); alpar@404: } alpar@404: _level->initFinish(); alpar@404: alpar@404: for (OutArcIt e(_graph, _source); e != INVALID; ++e) { alpar@404: if (_tolerance.positive((*_capacity)[e])) { alpar@404: Node u = _graph.target(e); alpar@404: if ((*_level)[u] == _level->maxLevel()) continue; alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: _excess->set(u, (*_excess)[u] + (*_capacity)[e]); alpar@404: if (u != _target && !_level->active(u)) { alpar@404: _level->activate(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: } alpar@404: alpar@404: /// \brief Initializes the internal data structures. alpar@404: /// alpar@404: /// Initializes the internal data structures and sets the initial alpar@404: /// flow to the given \c flowMap. The \c flowMap should contain a alpar@404: /// flow or at least a preflow, ie. in each node excluding the alpar@404: /// target the incoming flow should greater or equal to the alpar@404: /// outgoing flow. alpar@404: /// \return %False when the given \c flowMap is not a preflow. alpar@404: template kpeter@407: bool init(const FlowMap& flowMap) { alpar@404: createStructures(); alpar@404: alpar@404: for (ArcIt e(_graph); e != INVALID; ++e) { alpar@404: _flow->set(e, flowMap[e]); alpar@404: } alpar@404: alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: Value excess = 0; alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: excess += (*_flow)[e]; alpar@404: } alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: excess -= (*_flow)[e]; alpar@404: } alpar@404: if (excess < 0 && n != _source) return false; alpar@404: _excess->set(n, excess); alpar@404: } alpar@404: alpar@404: typename Digraph::template NodeMap reached(_graph, false); alpar@404: alpar@404: _level->initStart(); alpar@404: _level->initAddItem(_target); alpar@404: alpar@404: std::vector queue; alpar@404: reached.set(_source, true); alpar@404: alpar@404: queue.push_back(_target); alpar@404: reached.set(_target, true); alpar@404: while (!queue.empty()) { alpar@404: _level->initNewLevel(); alpar@404: std::vector nqueue; alpar@404: for (int i = 0; i < int(queue.size()); ++i) { alpar@404: Node n = queue[i]; alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node u = _graph.source(e); alpar@404: if (!reached[u] && alpar@404: _tolerance.positive((*_capacity)[e] - (*_flow)[e])) { alpar@404: reached.set(u, true); alpar@404: _level->initAddItem(u); alpar@404: nqueue.push_back(u); alpar@404: } alpar@404: } alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node v = _graph.target(e); alpar@404: if (!reached[v] && _tolerance.positive((*_flow)[e])) { alpar@404: reached.set(v, true); alpar@404: _level->initAddItem(v); alpar@404: nqueue.push_back(v); alpar@404: } alpar@404: } alpar@404: } alpar@404: queue.swap(nqueue); alpar@404: } alpar@404: _level->initFinish(); alpar@404: alpar@404: for (OutArcIt e(_graph, _source); e != INVALID; ++e) { alpar@404: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (_tolerance.positive(rem)) { alpar@404: Node u = _graph.target(e); alpar@404: if ((*_level)[u] == _level->maxLevel()) continue; alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: _excess->set(u, (*_excess)[u] + rem); alpar@404: if (u != _target && !_level->active(u)) { alpar@404: _level->activate(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: for (InArcIt e(_graph, _source); e != INVALID; ++e) { alpar@404: Value rem = (*_flow)[e]; alpar@404: if (_tolerance.positive(rem)) { alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] == _level->maxLevel()) continue; alpar@404: _flow->set(e, 0); alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: if (v != _target && !_level->active(v)) { alpar@404: _level->activate(v); alpar@404: } alpar@404: } alpar@404: } alpar@404: return true; alpar@404: } alpar@404: alpar@404: /// \brief Starts the first phase of the preflow algorithm. alpar@404: /// alpar@404: /// The preflow algorithm consists of two phases, this method runs alpar@404: /// the first phase. After the first phase the maximum flow value alpar@404: /// and a minimum value cut can already be computed, although a alpar@404: /// maximum flow is not yet obtained. So after calling this method alpar@404: /// \ref flowValue() returns the value of a maximum flow and \ref alpar@404: /// minCut() returns a minimum cut. alpar@404: /// \pre One of the \ref init() functions should be called. alpar@404: void startFirstPhase() { alpar@404: _phase = true; alpar@404: alpar@404: Node n = _level->highestActive(); alpar@404: int level = _level->highestActiveLevel(); alpar@404: while (n != INVALID) { alpar@404: int num = _node_num; alpar@404: alpar@404: while (num > 0 && n != INVALID) { alpar@404: Value excess = (*_excess)[n]; alpar@404: int new_level = _level->maxLevel(); alpar@404: alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.target(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] + excess); alpar@404: _excess->set(v, (*_excess)[v] + excess); alpar@404: excess = 0; alpar@404: goto no_more_push_1; alpar@404: } else { alpar@404: excess -= rem; alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Value rem = (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] - excess); alpar@404: _excess->set(v, (*_excess)[v] + excess); alpar@404: excess = 0; alpar@404: goto no_more_push_1; alpar@404: } else { alpar@404: excess -= rem; alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: no_more_push_1: alpar@404: alpar@404: _excess->set(n, excess); alpar@404: alpar@404: if (excess != 0) { alpar@404: if (new_level + 1 < _level->maxLevel()) { alpar@404: _level->liftHighestActive(new_level + 1); alpar@404: } else { alpar@404: _level->liftHighestActiveToTop(); alpar@404: } alpar@404: if (_level->emptyLevel(level)) { alpar@404: _level->liftToTop(level); alpar@404: } alpar@404: } else { alpar@404: _level->deactivate(n); alpar@404: } alpar@404: alpar@404: n = _level->highestActive(); alpar@404: level = _level->highestActiveLevel(); alpar@404: --num; alpar@404: } alpar@404: alpar@404: num = _node_num * 20; alpar@404: while (num > 0 && n != INVALID) { alpar@404: Value excess = (*_excess)[n]; alpar@404: int new_level = _level->maxLevel(); alpar@404: alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.target(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] + excess); alpar@404: _excess->set(v, (*_excess)[v] + excess); alpar@404: excess = 0; alpar@404: goto no_more_push_2; alpar@404: } else { alpar@404: excess -= rem; alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Value rem = (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] - excess); alpar@404: _excess->set(v, (*_excess)[v] + excess); alpar@404: excess = 0; alpar@404: goto no_more_push_2; alpar@404: } else { alpar@404: excess -= rem; alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: no_more_push_2: alpar@404: alpar@404: _excess->set(n, excess); alpar@404: alpar@404: if (excess != 0) { alpar@404: if (new_level + 1 < _level->maxLevel()) { alpar@404: _level->liftActiveOn(level, new_level + 1); alpar@404: } else { alpar@404: _level->liftActiveToTop(level); alpar@404: } alpar@404: if (_level->emptyLevel(level)) { alpar@404: _level->liftToTop(level); alpar@404: } alpar@404: } else { alpar@404: _level->deactivate(n); alpar@404: } alpar@404: alpar@404: while (level >= 0 && _level->activeFree(level)) { alpar@404: --level; alpar@404: } alpar@404: if (level == -1) { alpar@404: n = _level->highestActive(); alpar@404: level = _level->highestActiveLevel(); alpar@404: } else { alpar@404: n = _level->activeOn(level); alpar@404: } alpar@404: --num; alpar@404: } alpar@404: } alpar@404: } alpar@404: alpar@404: /// \brief Starts the second phase of the preflow algorithm. alpar@404: /// alpar@404: /// The preflow algorithm consists of two phases, this method runs alpar@404: /// the second phase. After calling \ref init() and \ref alpar@404: /// startFirstPhase() and then \ref startSecondPhase(), \ref alpar@404: /// flowMap() return a maximum flow, \ref flowValue() returns the alpar@404: /// value of a maximum flow, \ref minCut() returns a minimum cut alpar@404: /// \pre The \ref init() and startFirstPhase() functions should be alpar@404: /// called before. alpar@404: void startSecondPhase() { alpar@404: _phase = false; alpar@404: alpar@404: typename Digraph::template NodeMap reached(_graph); alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: reached.set(n, (*_level)[n] < _level->maxLevel()); alpar@404: } alpar@404: alpar@404: _level->initStart(); alpar@404: _level->initAddItem(_source); alpar@404: alpar@404: std::vector queue; alpar@404: queue.push_back(_source); alpar@404: reached.set(_source, true); alpar@404: alpar@404: while (!queue.empty()) { alpar@404: _level->initNewLevel(); alpar@404: std::vector nqueue; alpar@404: for (int i = 0; i < int(queue.size()); ++i) { alpar@404: Node n = queue[i]; alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node v = _graph.target(e); alpar@404: if (!reached[v] && _tolerance.positive((*_flow)[e])) { alpar@404: reached.set(v, true); alpar@404: _level->initAddItem(v); alpar@404: nqueue.push_back(v); alpar@404: } alpar@404: } alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node u = _graph.source(e); alpar@404: if (!reached[u] && alpar@404: _tolerance.positive((*_capacity)[e] - (*_flow)[e])) { alpar@404: reached.set(u, true); alpar@404: _level->initAddItem(u); alpar@404: nqueue.push_back(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: queue.swap(nqueue); alpar@404: } alpar@404: _level->initFinish(); alpar@404: alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: if (!reached[n]) { alpar@404: _level->dirtyTopButOne(n); alpar@404: } else if ((*_excess)[n] > 0 && _target != n) { alpar@404: _level->activate(n); alpar@404: } alpar@404: } alpar@404: alpar@404: Node n; alpar@404: while ((n = _level->highestActive()) != INVALID) { alpar@404: Value excess = (*_excess)[n]; alpar@404: int level = _level->highestActiveLevel(); alpar@404: int new_level = _level->maxLevel(); alpar@404: alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.target(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _source) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] + excess); alpar@404: _excess->set(v, (*_excess)[v] + excess); alpar@404: excess = 0; alpar@404: goto no_more_push; alpar@404: } else { alpar@404: excess -= rem; alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Value rem = (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _source) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] - excess); alpar@404: _excess->set(v, (*_excess)[v] + excess); alpar@404: excess = 0; alpar@404: goto no_more_push; alpar@404: } else { alpar@404: excess -= rem; alpar@404: _excess->set(v, (*_excess)[v] + rem); alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: no_more_push: alpar@404: alpar@404: _excess->set(n, excess); alpar@404: alpar@404: if (excess != 0) { alpar@404: if (new_level + 1 < _level->maxLevel()) { alpar@404: _level->liftHighestActive(new_level + 1); alpar@404: } else { alpar@404: // Calculation error alpar@404: _level->liftHighestActiveToTop(); alpar@404: } alpar@404: if (_level->emptyLevel(level)) { alpar@404: // Calculation error alpar@404: _level->liftToTop(level); alpar@404: } alpar@404: } else { alpar@404: _level->deactivate(n); alpar@404: } alpar@404: alpar@404: } alpar@404: } alpar@404: alpar@404: /// \brief Runs the preflow algorithm. alpar@404: /// alpar@404: /// Runs the preflow algorithm. alpar@404: /// \note pf.run() is just a shortcut of the following code. alpar@404: /// \code alpar@404: /// pf.init(); alpar@404: /// pf.startFirstPhase(); alpar@404: /// pf.startSecondPhase(); alpar@404: /// \endcode alpar@404: void run() { alpar@404: init(); alpar@404: startFirstPhase(); alpar@404: startSecondPhase(); alpar@404: } alpar@404: alpar@404: /// \brief Runs the preflow algorithm to compute the minimum cut. alpar@404: /// alpar@404: /// Runs the preflow algorithm to compute the minimum cut. alpar@404: /// \note pf.runMinCut() is just a shortcut of the following code. alpar@404: /// \code alpar@404: /// pf.init(); alpar@404: /// pf.startFirstPhase(); alpar@404: /// \endcode alpar@404: void runMinCut() { alpar@404: init(); alpar@404: startFirstPhase(); alpar@404: } alpar@404: alpar@404: /// @} alpar@404: alpar@404: /// \name Query Functions alpar@404: /// The result of the %Preflow algorithm can be obtained using these alpar@404: /// functions.\n alpar@404: /// Before the use of these functions, alpar@404: /// either run() or start() must be called. alpar@404: alpar@404: ///@{ alpar@404: alpar@404: /// \brief Returns the value of the maximum flow. alpar@404: /// alpar@404: /// Returns the value of the maximum flow by returning the excess alpar@404: /// of the target node \c t. This value equals to the value of alpar@404: /// the maximum flow already after the first phase. alpar@404: Value flowValue() const { alpar@404: return (*_excess)[_target]; alpar@404: } alpar@404: alpar@404: /// \brief Returns true when the node is on the source side of minimum cut. alpar@404: /// alpar@404: /// Returns true when the node is on the source side of minimum alpar@404: /// cut. This method can be called both after running \ref alpar@404: /// startFirstPhase() and \ref startSecondPhase(). alpar@404: bool minCut(const Node& node) const { alpar@404: return ((*_level)[node] == _level->maxLevel()) == _phase; alpar@404: } alpar@404: alpar@404: /// \brief Returns a minimum value cut. alpar@404: /// alpar@404: /// Sets the \c cutMap to the characteristic vector of a minimum value alpar@404: /// cut. This method can be called both after running \ref alpar@404: /// startFirstPhase() and \ref startSecondPhase(). The result after second alpar@404: /// phase could be changed slightly if inexact computation is used. alpar@404: /// \pre The \c cutMap should be a bool-valued node-map. alpar@404: template alpar@404: void minCutMap(CutMap& cutMap) const { alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: cutMap.set(n, minCut(n)); alpar@404: } alpar@404: } alpar@404: alpar@404: /// \brief Returns the flow on the arc. alpar@404: /// alpar@404: /// Sets the \c flowMap to the flow on the arcs. This method can alpar@404: /// be called after the second phase of algorithm. alpar@404: Value flow(const Arc& arc) const { alpar@404: return (*_flow)[arc]; alpar@404: } alpar@404: alpar@404: /// @} alpar@404: }; alpar@404: } alpar@404: alpar@404: #endif