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_GOLDBERG_TARJAN_H deba@2514: #define LEMON_GOLDBERG_TARJAN_H deba@2514: deba@2514: #include deba@2514: #include deba@2514: deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: #include deba@2514: deba@2514: /// \file deba@2514: /// \ingroup max_flow deba@2514: /// \brief Implementation of the preflow algorithm. deba@2514: deba@2514: namespace lemon { deba@2514: deba@2514: /// \brief Default traits class of GoldbergTarjan class. deba@2514: /// deba@2514: /// Default traits class of GoldbergTarjan class. deba@2514: /// \param _Graph Graph type. deba@2514: /// \param _CapacityMap Type of capacity map. deba@2514: template deba@2514: struct GoldbergTarjanDefaultTraits { 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 eleavator type used by GoldbergTarjan algorithm. deba@2514: /// deba@2514: /// The elevator type used by GoldbergTarjan algorithm. deba@2514: /// deba@2514: /// \sa Elevator deba@2514: /// \sa LinkedElevator deba@2514: typedef LinkedElevator Elevator; deba@2514: deba@2514: /// \brief Instantiates an Elevator. deba@2514: /// deba@2514: /// This function instantiates a \ref Elevator. deba@2514: /// \param graph The graph, to which we would like to define the elevator. deba@2514: /// \param max_level The maximum level of the elevator. deba@2514: static Elevator* createElevator(const Graph& graph, int max_level) { deba@2514: return new Elevator(graph, max_level); 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: /// \brief Goldberg-Tarjan algorithms class. deba@2514: /// deba@2514: /// This class provides an implementation of the \e GoldbergTarjan deba@2514: /// \e algorithm producing a flow of maximum value in a directed deba@2514: /// graph. The GoldbergTarjan algorithm is a theoretical improvement deba@2514: /// of the Goldberg's \ref Preflow "preflow" algorithm by using the \ref deba@2514: /// DynamicTree "dynamic tree" data structure of Sleator and Tarjan. deba@2514: /// deba@2522: /// The original preflow algorithm with \e highest \e label deba@2522: /// heuristic has \f$O(n^2\sqrt{e})\f$ or with \e FIFO heuristic has deba@2522: /// \f$O(n^3)\f$ time complexity. The current algorithm improved deba@2522: /// this complexity to \f$O(nm\log(\frac{n^2}{m}))\f$. The algorithm deba@2522: /// builds limited size dynamic trees on the residual graph, which deba@2522: /// can be used to make multilevel push operations and gives a deba@2522: /// better bound on the number of non-saturating pushes. 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: /// GoldbergTarjanDefaultTraits. See \ref deba@2514: /// GoldbergTarjanDefaultTraits for the documentation of a deba@2514: /// Goldberg-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: GoldbergTarjanDefaultTraits<_Graph, _CapacityMap> > deba@2514: #endif deba@2514: class GoldbergTarjan { 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::Elevator Elevator; deba@2514: typedef typename Traits::Tolerance Tolerance; deba@2514: deba@2514: protected: deba@2514: deba@2514: GRAPH_TYPEDEFS(typename Graph); deba@2514: deba@2514: typedef typename Graph::template NodeMap NodeNodeMap; deba@2514: typedef typename Graph::template NodeMap IntNodeMap; deba@2514: deba@2514: typedef typename Graph::template NodeMap EdgeNodeMap; deba@2514: typedef typename Graph::template EdgeMap EdgeEdgeMap; deba@2514: deba@2514: typedef typename std::vector VecNode; deba@2514: deba@2514: typedef DynamicTree DynTree; deba@2514: deba@2514: const Graph& _graph; deba@2514: const CapacityMap* _capacity; deba@2514: int _node_num; //the number of nodes of G deba@2514: deba@2514: Node _source; deba@2514: Node _target; deba@2514: deba@2514: FlowMap* _flow; deba@2514: bool _local_flow; deba@2514: deba@2514: Elevator* _level; deba@2514: bool _local_level; deba@2514: deba@2514: typedef typename Graph::template NodeMap ExcessMap; deba@2514: ExcessMap* _excess; deba@2514: deba@2514: Tolerance _tolerance; deba@2514: deba@2514: bool _phase; deba@2514: deba@2514: // constant for treesize deba@2514: static const double _tree_bound = 2; deba@2514: int _max_tree_size; deba@2514: deba@2514: //tags for the dynamic tree deba@2514: DynTree *_dt; deba@2514: //datastructure of dyanamic tree deba@2514: IntNodeMap *_dt_index; deba@2514: //datastrucure for solution of the communication between the two class deba@2514: EdgeNodeMap *_dt_edges; deba@2514: //nodeMap for storing the outgoing edge from the node in the tree deba@2514: deba@2514: //max of the type Value deba@2514: const Value _max_value; deba@2514: deba@2514: public: deba@2514: deba@2514: typedef GoldbergTarjan 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 GoldbergTarjan > { deba@2514: typedef GoldbergTarjan > 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: /// \brief \ref named-templ-param "Named parameter" for setting deba@2514: /// Elevator type deba@2514: /// deba@2514: /// \ref named-templ-param "Named parameter" for setting Elevator deba@2514: /// type deba@2514: template deba@2514: struct DefElevator deba@2514: : public GoldbergTarjan > { deba@2514: typedef GoldbergTarjan > Create; deba@2514: }; deba@2514: deba@2514: template deba@2514: struct DefStandardElevatorTraits : public Traits { deba@2514: typedef _Elevator Elevator; deba@2514: static Elevator *createElevator(const Graph& graph, int max_level) { deba@2514: return new Elevator(graph, max_level); deba@2514: } deba@2514: }; deba@2514: deba@2514: /// \brief \ref named-templ-param "Named parameter" for setting deba@2514: /// Elevator type deba@2514: /// deba@2514: /// \ref named-templ-param "Named parameter" for setting Elevator deba@2514: /// type. The Elevator should be standard constructor interface, ie. deba@2514: /// the graph and the maximum level should be passed to it. deba@2514: template deba@2514: struct DefStandardElevator deba@2514: : public GoldbergTarjan > { deba@2514: typedef GoldbergTarjan > Create; deba@2514: }; deba@2514: deba@2514: deba@2514: ///\ref Exception for the case when s=t. deba@2514: deba@2514: ///\ref Exception for the case when the source equals the target. deba@2514: class InvalidArgument : public lemon::LogicError { deba@2514: public: deba@2514: virtual const char* what() const throw() { deba@2514: return "lemon::GoldbergTarjan::InvalidArgument"; deba@2514: } deba@2514: }; deba@2514: deba@2527: protected: deba@2527: deba@2527: GoldbergTarjan() {} deba@2527: deba@2527: public: deba@2514: 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: /// Except the graph, all of these parameters can be reset by deba@2514: /// calling \ref source, \ref target, \ref capacityMap and \ref deba@2514: /// flowMap, resp. deba@2514: GoldbergTarjan(const Graph& graph, const CapacityMap& capacity, deba@2514: Node source, Node target) deba@2514: : _graph(graph), _capacity(&capacity), deba@2514: _node_num(), _source(source), _target(target), deba@2514: _flow(0), _local_flow(false), deba@2514: _level(0), _local_level(false), deba@2514: _excess(0), _tolerance(), deba@2514: _phase(), _max_tree_size(), deba@2514: _dt(0), _dt_index(0), _dt_edges(0), deba@2514: _max_value(std::numeric_limits::max()) { deba@2514: if (_source == _target) throw InvalidArgument(); deba@2514: } deba@2514: deba@2514: /// \brief Destrcutor. deba@2514: /// deba@2514: /// Destructor. deba@2514: ~GoldbergTarjan() { 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: GoldbergTarjan& 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: GoldbergTarjan& 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 elevator. deba@2514: /// deba@2514: /// Sets the elevator. deba@2514: /// \return \c (*this) deba@2514: GoldbergTarjan& elevator(Elevator& elevator) { deba@2514: if (_local_level) { deba@2514: delete _level; deba@2514: _local_level = false; deba@2514: } deba@2514: _level = &elevator; deba@2514: return *this; deba@2514: } deba@2514: deba@2514: /// \brief Returns the elevator. deba@2514: /// deba@2514: /// \return The elevator. deba@2514: const Elevator& elevator() { deba@2514: return *_level; 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: GoldbergTarjan& 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: GoldbergTarjan& 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: GoldbergTarjan& 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: deba@2514: private: deba@2514: deba@2514: void createStructures() { deba@2514: _node_num = countNodes(_graph); deba@2514: deba@2518: _max_tree_size = int((double(_node_num) * double(_node_num)) / deba@2518: double(countEdges(_graph))); deba@2514: deba@2514: if (!_flow) { deba@2514: _flow = Traits::createFlowMap(_graph); deba@2514: _local_flow = true; deba@2514: } deba@2514: if (!_level) { deba@2514: _level = Traits::createElevator(_graph, _node_num); deba@2514: _local_level = true; deba@2514: } deba@2514: if (!_excess) { deba@2514: _excess = new ExcessMap(_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@2514: } deba@2514: deba@2514: void destroyStructures() { deba@2514: if (_local_flow) { deba@2514: delete _flow; deba@2514: } deba@2514: if (_local_level) { deba@2514: delete _level; deba@2514: } deba@2514: if (_excess) { deba@2514: delete _excess; 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 sendOut(Node n, Value& excess) { 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: if (_tolerance.positive(rem) && !_level->active(w) && w != _target) { deba@2514: _level->activate(w); deba@2514: } deba@2514: deba@2514: if (!_tolerance.less(rem, excess)) { deba@2514: _dt->addCost(n, - excess); deba@2514: _excess->set(w, (*_excess)[w] + excess); deba@2514: excess = 0; deba@2514: return true; deba@2514: } deba@2514: deba@2514: deba@2514: _dt->addCost(n, - rem); deba@2514: deba@2514: excess -= rem; deba@2514: _excess->set(w, (*_excess)[w] + rem); deba@2514: deba@2514: _dt->cut(u); 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]); deba@2514: } else { deba@2514: _flow->set(e, 0); deba@2514: } deba@2514: deba@2514: w = _dt->findRoot(n); deba@2514: } deba@2514: return false; deba@2514: } deba@2514: deba@2514: bool sendIn(Node n, Value& excess) { 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: if (_tolerance.positive(rem) && !_level->active(w) && w != _source) { deba@2514: _level->activate(w); deba@2514: } deba@2514: deba@2514: if (!_tolerance.less(rem, excess)) { deba@2514: _dt->addCost(n, - excess); deba@2514: _excess->set(w, (*_excess)[w] + excess); deba@2514: excess = 0; deba@2514: return true; deba@2514: } deba@2514: deba@2514: deba@2514: _dt->addCost(n, - rem); deba@2514: deba@2514: excess -= rem; deba@2514: _excess->set(w, (*_excess)[w] + rem); deba@2514: deba@2514: _dt->cut(u); 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]); deba@2514: } else { deba@2514: _flow->set(e, 0); deba@2514: } deba@2514: deba@2514: w = _dt->findRoot(n); deba@2514: } deba@2514: return false; deba@2514: } deba@2514: deba@2514: void cutChildren(Node n) { deba@2514: deba@2514: for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: deba@2514: Node v = _graph.target(e); deba@2514: deba@2514: if ((*_dt_edges)[v] != INVALID && (*_dt_edges)[v] == e) { deba@2514: _dt->cut(v); deba@2514: _dt_edges->set(v, INVALID); deba@2514: Value rem; deba@2514: _dt->findCost(v, rem); deba@2514: _dt->addCost(v, - rem); deba@2514: _dt->addCost(v, _max_value); deba@2514: _flow->set(e, rem); deba@2514: deba@2514: } deba@2514: } deba@2514: deba@2514: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: deba@2514: Node v = _graph.source(e); deba@2514: deba@2514: if ((*_dt_edges)[v] != INVALID && (*_dt_edges)[v] == e) { deba@2514: _dt->cut(v); deba@2514: _dt_edges->set(v, INVALID); deba@2514: Value rem; deba@2514: _dt->findCost(v, rem); deba@2514: _dt->addCost(v, - rem); deba@2514: _dt->addCost(v, _max_value); deba@2514: _flow->set(e, (*_capacity)[e] - rem); deba@2514: 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: public: deba@2514: deba@2514: /// \name Execution control The simplest way to execute the deba@2514: /// algorithm is to use one of the member functions called \c deba@2514: /// run(). 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 startFirstPhase() and if you need the startSecondPhase(). deba@2514: deba@2514: ///@{ deba@2514: deba@2514: /// \brief Initializes the internal data structures. deba@2514: /// deba@2514: /// Initializes the internal data structures. deba@2514: /// deba@2514: void init() { deba@2514: createStructures(); deba@2514: deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: _excess->set(n, 0); deba@2514: } deba@2514: deba@2514: for (EdgeIt e(_graph); e != INVALID; ++e) { deba@2514: _flow->set(e, 0); deba@2514: } deba@2514: deba@2514: _dt->clear(); deba@2514: for (NodeIt v(_graph); v != INVALID; ++v) { deba@2514: (*_dt_edges)[v] = INVALID; deba@2514: _dt->makeTree(v); deba@2514: _dt->addCost(v, _max_value); deba@2514: } deba@2514: deba@2514: typename Graph::template NodeMap reached(_graph, false); deba@2514: deba@2514: _level->initStart(); deba@2514: _level->initAddItem(_target); deba@2514: deba@2514: std::vector queue; deba@2514: reached.set(_source, true); deba@2514: deba@2514: queue.push_back(_target); deba@2514: reached.set(_target, true); deba@2514: while (!queue.empty()) { deba@2514: _level->initNewLevel(); deba@2514: std::vector nqueue; deba@2514: for (int i = 0; i < int(queue.size()); ++i) { deba@2514: Node n = queue[i]; deba@2514: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Node u = _graph.source(e); deba@2514: if (!reached[u] && _tolerance.positive((*_capacity)[e])) { deba@2514: reached.set(u, true); deba@2514: _level->initAddItem(u); deba@2514: nqueue.push_back(u); deba@2514: } deba@2514: } deba@2514: } deba@2514: queue.swap(nqueue); deba@2514: } deba@2514: _level->initFinish(); deba@2514: deba@2514: for (OutEdgeIt e(_graph, _source); e != INVALID; ++e) { deba@2514: if (_tolerance.positive((*_capacity)[e])) { deba@2514: Node u = _graph.target(e); deba@2514: if ((*_level)[u] == _level->maxLevel()) continue; deba@2514: _flow->set(e, (*_capacity)[e]); deba@2514: _excess->set(u, (*_excess)[u] + (*_capacity)[e]); deba@2514: if (u != _target && !_level->active(u)) { deba@2514: _level->activate(u); deba@2514: } deba@2514: } deba@2514: } deba@2514: } deba@2514: deba@2514: /// \brief Starts the first phase of the preflow algorithm. deba@2514: /// deba@2514: /// The preflow algorithm consists of two phases, this method runs deba@2514: /// the first phase. After the first phase the maximum flow value deba@2514: /// and a minimum value cut can already be computed, although a deba@2514: /// maximum flow is not yet obtained. So after calling this method deba@2514: /// \ref flowValue() returns the value of a maximum flow and \ref deba@2514: /// minCut() returns a minimum cut. deba@2514: /// \pre One of the \ref init() functions should be called. deba@2514: void startFirstPhase() { deba@2514: _phase = true; deba@2514: Node n; deba@2514: deba@2514: while ((n = _level->highestActive()) != INVALID) { deba@2514: Value excess = (*_excess)[n]; deba@2514: int level = _level->highestActiveLevel(); deba@2514: int new_level = _level->maxLevel(); deba@2514: deba@2514: if (_dt->findRoot(n) != n) { deba@2514: if (sendOut(n, excess)) goto no_more_push; deba@2514: } deba@2514: deba@2514: for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Value rem = (*_capacity)[e] - (*_flow)[e]; deba@2514: Node v = _graph.target(e); deba@2514: deba@2514: if (!_tolerance.positive(rem) && (*_dt_edges)[v] != e) continue; deba@2514: deba@2514: if ((*_level)[v] < level) { deba@2514: deba@2514: if (_dt->findSize(n) + _dt->findSize(v) < deba@2514: _tree_bound * _max_tree_size) { deba@2514: _dt->addCost(n, -_max_value); deba@2514: _dt->addCost(n, rem); deba@2514: _dt->link(n, v); deba@2514: _dt_edges->set(n, e); deba@2514: if (sendOut(n, excess)) goto no_more_push; deba@2514: } else { deba@2514: if (!_level->active(v) && v != _target) { deba@2514: _level->activate(v); deba@2514: } deba@2514: if (!_tolerance.less(rem, excess)) { deba@2514: _flow->set(e, (*_flow)[e] + excess); deba@2514: _excess->set(v, (*_excess)[v] + excess); deba@2514: excess = 0; deba@2514: goto no_more_push; deba@2514: } else { deba@2514: excess -= rem; deba@2514: _excess->set(v, (*_excess)[v] + rem); deba@2514: _flow->set(e, (*_capacity)[e]); deba@2514: } deba@2514: } deba@2514: } else if (new_level > (*_level)[v]) { deba@2514: new_level = (*_level)[v]; deba@2514: } deba@2514: } deba@2514: deba@2514: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Value rem = (*_flow)[e]; deba@2514: Node v = _graph.source(e); deba@2514: if (!_tolerance.positive(rem) && (*_dt_edges)[v] != e) continue; deba@2514: deba@2514: if ((*_level)[v] < level) { deba@2514: deba@2514: if (_dt->findSize(n) + _dt->findSize(v) < deba@2514: _tree_bound * _max_tree_size) { deba@2514: _dt->addCost(n, - _max_value); deba@2514: _dt->addCost(n, rem); deba@2514: _dt->link(n, v); deba@2514: _dt_edges->set(n, e); deba@2514: if (sendOut(n, excess)) goto no_more_push; deba@2514: } else { deba@2514: if (!_level->active(v) && v != _target) { deba@2514: _level->activate(v); deba@2514: } deba@2514: if (!_tolerance.less(rem, excess)) { deba@2514: _flow->set(e, (*_flow)[e] - excess); deba@2514: _excess->set(v, (*_excess)[v] + excess); deba@2514: excess = 0; deba@2514: goto no_more_push; deba@2514: } else { deba@2514: excess -= rem; deba@2514: _excess->set(v, (*_excess)[v] + rem); deba@2514: _flow->set(e, 0); deba@2514: } deba@2514: } deba@2514: } else if (new_level > (*_level)[v]) { deba@2514: new_level = (*_level)[v]; deba@2514: } deba@2514: } deba@2514: deba@2514: no_more_push: deba@2514: deba@2514: _excess->set(n, excess); deba@2514: deba@2514: if (excess != 0) { deba@2514: cutChildren(n); deba@2514: if (new_level + 1 < _level->maxLevel()) { deba@2514: _level->liftHighestActive(new_level + 1); deba@2514: } else { deba@2514: _level->liftHighestActiveToTop(); deba@2514: } deba@2514: if (_level->emptyLevel(level)) { deba@2514: _level->liftToTop(level); deba@2514: } deba@2514: } else { deba@2514: _level->deactivate(n); deba@2514: } deba@2514: } deba@2514: extractTrees(); deba@2514: } deba@2514: deba@2514: /// \brief Starts the second phase of the preflow algorithm. deba@2514: /// deba@2514: /// The preflow algorithm consists of two phases, this method runs deba@2514: /// the second phase. After calling \ref init() and \ref deba@2514: /// startFirstPhase() and then \ref startSecondPhase(), \ref deba@2514: /// flowMap() return a maximum flow, \ref flowValue() returns the deba@2514: /// value of a maximum flow, \ref minCut() returns a minimum cut deba@2514: /// \pre The \ref init() and startFirstPhase() functions should be deba@2514: /// called before. deba@2514: void startSecondPhase() { deba@2514: _phase = false; deba@2514: deba@2514: typename Graph::template NodeMap reached(_graph, false); deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2514: reached.set(n, (*_level)[n] < _level->maxLevel()); deba@2514: } deba@2514: deba@2514: _level->initStart(); deba@2514: _level->initAddItem(_source); deba@2514: deba@2514: std::vector queue; deba@2514: queue.push_back(_source); deba@2514: reached.set(_source, true); deba@2514: deba@2514: while (!queue.empty()) { deba@2514: _level->initNewLevel(); deba@2514: std::vector nqueue; deba@2514: for (int i = 0; i < int(queue.size()); ++i) { deba@2514: Node n = queue[i]; deba@2514: for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Node v = _graph.target(e); deba@2514: if (!reached[v] && _tolerance.positive((*_flow)[e])) { deba@2514: reached.set(v, true); deba@2514: _level->initAddItem(v); deba@2514: nqueue.push_back(v); deba@2514: } deba@2514: } deba@2514: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Node u = _graph.source(e); deba@2514: if (!reached[u] && deba@2514: _tolerance.positive((*_capacity)[e] - (*_flow)[e])) { deba@2514: reached.set(u, true); deba@2514: _level->initAddItem(u); deba@2514: nqueue.push_back(u); deba@2514: } deba@2514: } deba@2514: } deba@2514: queue.swap(nqueue); deba@2514: } deba@2514: _level->initFinish(); deba@2514: deba@2514: for (NodeIt n(_graph); n != INVALID; ++n) { deba@2518: if (!reached[n]) { deba@2518: _level->markToBottom(n); deba@2518: } else if ((*_excess)[n] > 0 && _target != n) { deba@2514: _level->activate(n); deba@2514: } deba@2514: } deba@2514: deba@2514: Node n; deba@2514: deba@2514: while ((n = _level->highestActive()) != INVALID) { deba@2514: Value excess = (*_excess)[n]; deba@2514: int level = _level->highestActiveLevel(); deba@2514: int new_level = _level->maxLevel(); deba@2514: deba@2514: if (_dt->findRoot(n) != n) { deba@2514: if (sendIn(n, excess)) goto no_more_push; deba@2514: } deba@2514: deba@2514: for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Value rem = (*_capacity)[e] - (*_flow)[e]; deba@2514: Node v = _graph.target(e); deba@2514: deba@2514: if (!_tolerance.positive(rem) && (*_dt_edges)[v] != e) continue; deba@2514: deba@2514: if ((*_level)[v] < level) { deba@2514: deba@2514: if (_dt->findSize(n) + _dt->findSize(v) < deba@2514: _tree_bound * _max_tree_size) { deba@2514: _dt->addCost(n, -_max_value); deba@2514: _dt->addCost(n, rem); deba@2514: _dt->link(n, v); deba@2514: _dt_edges->set(n, e); deba@2514: if (sendIn(n, excess)) goto no_more_push; deba@2514: } else { deba@2514: if (!_level->active(v) && v != _source) { deba@2514: _level->activate(v); deba@2514: } deba@2514: if (!_tolerance.less(rem, excess)) { deba@2514: _flow->set(e, (*_flow)[e] + excess); deba@2514: _excess->set(v, (*_excess)[v] + excess); deba@2514: excess = 0; deba@2514: goto no_more_push; deba@2514: } else { deba@2514: excess -= rem; deba@2514: _excess->set(v, (*_excess)[v] + rem); deba@2514: _flow->set(e, (*_capacity)[e]); deba@2514: } deba@2514: } deba@2514: } else if (new_level > (*_level)[v]) { deba@2514: new_level = (*_level)[v]; deba@2514: } deba@2514: } deba@2514: deba@2514: for (InEdgeIt e(_graph, n); e != INVALID; ++e) { deba@2514: Value rem = (*_flow)[e]; deba@2514: Node v = _graph.source(e); deba@2514: if (!_tolerance.positive(rem) && (*_dt_edges)[v] != e) continue; deba@2514: deba@2514: if ((*_level)[v] < level) { deba@2514: deba@2514: if (_dt->findSize(n) + _dt->findSize(v) < deba@2514: _tree_bound * _max_tree_size) { deba@2514: _dt->addCost(n, - _max_value); deba@2514: _dt->addCost(n, rem); deba@2514: _dt->link(n, v); deba@2514: _dt_edges->set(n, e); deba@2514: if (sendIn(n, excess)) goto no_more_push; deba@2514: } else { deba@2514: if (!_level->active(v) && v != _source) { deba@2514: _level->activate(v); deba@2514: } deba@2514: if (!_tolerance.less(rem, excess)) { deba@2514: _flow->set(e, (*_flow)[e] - excess); deba@2514: _excess->set(v, (*_excess)[v] + excess); deba@2514: excess = 0; deba@2514: goto no_more_push; deba@2514: } else { deba@2514: excess -= rem; deba@2514: _excess->set(v, (*_excess)[v] + rem); deba@2514: _flow->set(e, 0); deba@2514: } deba@2514: } deba@2514: } else if (new_level > (*_level)[v]) { deba@2514: new_level = (*_level)[v]; deba@2514: } deba@2514: } deba@2514: deba@2514: no_more_push: deba@2514: deba@2514: _excess->set(n, excess); deba@2514: deba@2514: if (excess != 0) { deba@2514: cutChildren(n); deba@2514: if (new_level + 1 < _level->maxLevel()) { deba@2514: _level->liftHighestActive(new_level + 1); deba@2514: } else { deba@2514: _level->liftHighestActiveToTop(); deba@2514: } deba@2514: if (_level->emptyLevel(level)) { deba@2514: _level->liftToTop(level); deba@2514: } deba@2514: } else { deba@2514: _level->deactivate(n); deba@2514: } deba@2514: } deba@2514: extractTrees(); deba@2514: } deba@2514: deba@2514: /// \brief Runs the Goldberg-Tarjan algorithm. deba@2514: /// deba@2514: /// Runs the Goldberg-Tarjan algorithm. deba@2514: /// \note pf.run() is just a shortcut of the following code. deba@2514: /// \code deba@2514: /// pf.init(); deba@2514: /// pf.startFirstPhase(); deba@2514: /// pf.startSecondPhase(); deba@2514: /// \endcode deba@2514: void run() { deba@2514: init(); deba@2514: startFirstPhase(); deba@2514: startSecondPhase(); deba@2514: } deba@2514: deba@2514: /// \brief Runs the Goldberg-Tarjan algorithm to compute the minimum cut. deba@2514: /// deba@2514: /// Runs the Goldberg-Tarjan algorithm to compute the minimum cut. deba@2514: /// \note pf.runMinCut() is just a shortcut of the following code. deba@2514: /// \code deba@2514: /// pf.init(); deba@2514: /// pf.startFirstPhase(); deba@2514: /// \endcode deba@2514: void runMinCut() { deba@2514: init(); deba@2514: startFirstPhase(); deba@2514: } deba@2514: deba@2514: /// @} deba@2514: deba@2522: /// \name Query Functions deba@2522: /// The result of the Goldberg-Tarjan algorithm can be obtained deba@2522: /// using these functions. deba@2522: /// \n deba@2522: /// Before the use of these functions, either run() or start() must deba@2522: /// 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 (*_excess)[_target]; deba@2514: } deba@2514: deba@2514: /// \brief Returns true when the node is on the source side of minimum cut. 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] == _level->maxLevel()) == _phase; deba@2514: } deba@2514: deba@2514: /// \brief Returns a minimum value cut. deba@2514: /// deba@2514: /// Sets the \c cutMap to the characteristic vector of a minimum value deba@2514: /// cut. This method can be called both after running \ref deba@2514: /// startFirstPhase() and \ref startSecondPhase(). The result after second deba@2514: /// phase could be changed slightly if inexact computation is used. deba@2514: /// \pre The \c cutMap should be a bool-valued node-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, minCut(n)); 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: /// @} deba@2514: deba@2514: }; deba@2514: deba@2514: } //namespace lemon deba@2514: deba@2514: #endif