deba@425: /* -*- mode: C++; indent-tabs-mode: nil; -*- deba@425: * deba@425: * This file is a part of LEMON, a generic C++ optimization library. deba@425: * alpar@463: * Copyright (C) 2003-2009 deba@425: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@425: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@425: * deba@425: * Permission to use, modify and distribute this software is granted deba@425: * provided that this copyright notice appears in all copies. For deba@425: * precise terms see the accompanying LICENSE file. deba@425: * deba@425: * This software is provided "AS IS" with no warranty of any kind, deba@425: * express or implied, and with no claim as to its suitability for any deba@425: * purpose. deba@425: * deba@425: */ deba@425: deba@425: #ifndef LEMON_HAO_ORLIN_H deba@425: #define LEMON_HAO_ORLIN_H deba@425: deba@425: #include deba@425: #include deba@425: #include deba@425: deba@425: #include deba@425: #include deba@425: #include deba@425: deba@425: /// \file deba@425: /// \ingroup min_cut deba@425: /// \brief Implementation of the Hao-Orlin algorithm. deba@425: /// kpeter@643: /// Implementation of the Hao-Orlin algorithm for finding a minimum cut kpeter@643: /// in a digraph. deba@425: deba@425: namespace lemon { deba@425: deba@425: /// \ingroup min_cut deba@425: /// kpeter@643: /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph. deba@425: /// kpeter@643: /// This class implements the Hao-Orlin algorithm for finding a minimum kpeter@643: /// value cut in a directed graph \f$D=(V,A)\f$. kpeter@643: /// It takes a fixed node \f$ source \in V \f$ and deba@425: /// consists of two phases: in the first phase it determines a deba@425: /// minimum cut with \f$ source \f$ on the source-side (i.e. a set kpeter@643: /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal outgoing kpeter@643: /// capacity) and in the second phase it determines a minimum cut deba@425: /// with \f$ source \f$ on the sink-side (i.e. a set kpeter@643: /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal outgoing kpeter@643: /// capacity). Obviously, the smaller of these two cuts will be a deba@425: /// minimum cut of \f$ D \f$. The algorithm is a modified kpeter@643: /// preflow push-relabel algorithm. Our implementation calculates deba@425: /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the deba@425: /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The kpeter@643: /// purpose of such algorithm is e.g. testing network reliability. deba@425: /// kpeter@643: /// For an undirected graph you can run just the first phase of the kpeter@643: /// algorithm or you can use the algorithm of Nagamochi and Ibaraki, kpeter@643: /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$ kpeter@643: /// time. It is implemented in the NagamochiIbaraki algorithm class. kpeter@643: /// kpeter@643: /// \tparam GR The type of the digraph the algorithm runs on. kpeter@643: /// \tparam CAP The type of the arc map containing the capacities, kpeter@643: /// which can be any numreric type. The default map type is kpeter@643: /// \ref concepts::Digraph::ArcMap "GR::ArcMap". kpeter@643: /// \tparam TOL Tolerance class for handling inexact computations. The kpeter@606: /// default tolerance type is \ref Tolerance "Tolerance". deba@425: #ifdef DOXYGEN kpeter@606: template deba@425: #else kpeter@606: template , kpeter@606: typename TOL = Tolerance > deba@425: #endif deba@425: class HaoOrlin { kpeter@643: public: kpeter@643: kpeter@643: /// The digraph type of the algorithm kpeter@643: typedef GR Digraph; kpeter@643: /// The capacity map type of the algorithm kpeter@643: typedef CAP CapacityMap; kpeter@643: /// The tolerance type of the algorithm kpeter@643: typedef TOL Tolerance; kpeter@643: deba@425: private: deba@425: deba@425: typedef typename CapacityMap::Value Value; deba@425: kpeter@643: TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); deba@425: deba@425: const Digraph& _graph; deba@425: const CapacityMap* _capacity; deba@425: deba@425: typedef typename Digraph::template ArcMap FlowMap; deba@425: FlowMap* _flow; deba@425: deba@425: Node _source; deba@425: deba@425: int _node_num; deba@425: deba@425: // Bucketing structure deba@425: std::vector _first, _last; deba@425: typename Digraph::template NodeMap* _next; deba@425: typename Digraph::template NodeMap* _prev; deba@425: typename Digraph::template NodeMap* _active; deba@425: typename Digraph::template NodeMap* _bucket; deba@425: deba@425: std::vector _dormant; deba@425: deba@425: std::list > _sets; deba@425: std::list::iterator _highest; deba@425: deba@425: typedef typename Digraph::template NodeMap ExcessMap; deba@425: ExcessMap* _excess; deba@425: deba@425: typedef typename Digraph::template NodeMap SourceSetMap; deba@425: SourceSetMap* _source_set; deba@425: deba@425: Value _min_cut; deba@425: deba@425: typedef typename Digraph::template NodeMap MinCutMap; deba@425: MinCutMap* _min_cut_map; deba@425: deba@425: Tolerance _tolerance; deba@425: deba@425: public: deba@425: deba@425: /// \brief Constructor deba@425: /// deba@425: /// Constructor of the algorithm class. deba@425: HaoOrlin(const Digraph& graph, const CapacityMap& capacity, deba@425: const Tolerance& tolerance = Tolerance()) : deba@425: _graph(graph), _capacity(&capacity), _flow(0), _source(), deba@425: _node_num(), _first(), _last(), _next(0), _prev(0), deba@425: _active(0), _bucket(0), _dormant(), _sets(), _highest(), deba@425: _excess(0), _source_set(0), _min_cut(), _min_cut_map(0), deba@425: _tolerance(tolerance) {} deba@425: deba@425: ~HaoOrlin() { deba@425: if (_min_cut_map) { deba@425: delete _min_cut_map; deba@425: } deba@425: if (_source_set) { deba@425: delete _source_set; deba@425: } deba@425: if (_excess) { deba@425: delete _excess; deba@425: } deba@425: if (_next) { deba@425: delete _next; deba@425: } deba@425: if (_prev) { deba@425: delete _prev; deba@425: } deba@425: if (_active) { deba@425: delete _active; deba@425: } deba@425: if (_bucket) { deba@425: delete _bucket; deba@425: } deba@425: if (_flow) { deba@425: delete _flow; deba@425: } deba@425: } deba@425: deba@425: private: deba@425: deba@425: void activate(const Node& i) { kpeter@628: (*_active)[i] = true; deba@425: deba@425: int bucket = (*_bucket)[i]; deba@425: deba@425: if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return; deba@425: //unlace kpeter@628: (*_next)[(*_prev)[i]] = (*_next)[i]; deba@425: if ((*_next)[i] != INVALID) { kpeter@628: (*_prev)[(*_next)[i]] = (*_prev)[i]; deba@425: } else { deba@425: _last[bucket] = (*_prev)[i]; deba@425: } deba@425: //lace kpeter@628: (*_next)[i] = _first[bucket]; kpeter@628: (*_prev)[_first[bucket]] = i; kpeter@628: (*_prev)[i] = INVALID; deba@425: _first[bucket] = i; deba@425: } deba@425: deba@425: void deactivate(const Node& i) { kpeter@628: (*_active)[i] = false; deba@425: int bucket = (*_bucket)[i]; deba@425: deba@425: if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return; deba@425: deba@425: //unlace kpeter@628: (*_prev)[(*_next)[i]] = (*_prev)[i]; deba@425: if ((*_prev)[i] != INVALID) { kpeter@628: (*_next)[(*_prev)[i]] = (*_next)[i]; deba@425: } else { deba@425: _first[bucket] = (*_next)[i]; deba@425: } deba@425: //lace kpeter@628: (*_prev)[i] = _last[bucket]; kpeter@628: (*_next)[_last[bucket]] = i; kpeter@628: (*_next)[i] = INVALID; deba@425: _last[bucket] = i; deba@425: } deba@425: deba@425: void addItem(const Node& i, int bucket) { deba@425: (*_bucket)[i] = bucket; deba@425: if (_last[bucket] != INVALID) { kpeter@628: (*_prev)[i] = _last[bucket]; kpeter@628: (*_next)[_last[bucket]] = i; kpeter@628: (*_next)[i] = INVALID; deba@425: _last[bucket] = i; deba@425: } else { kpeter@628: (*_prev)[i] = INVALID; deba@425: _first[bucket] = i; kpeter@628: (*_next)[i] = INVALID; deba@425: _last[bucket] = i; deba@425: } deba@425: } deba@425: deba@425: void findMinCutOut() { deba@425: deba@425: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@628: (*_excess)[n] = 0; deba@644: (*_source_set)[n] = false; deba@425: } deba@425: deba@425: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@628: (*_flow)[a] = 0; deba@425: } deba@425: deba@427: int bucket_num = 0; deba@427: std::vector queue(_node_num); deba@427: int qfirst = 0, qlast = 0, qsep = 0; deba@425: deba@425: { deba@425: typename Digraph::template NodeMap reached(_graph, false); deba@425: kpeter@628: reached[_source] = true; deba@425: bool first_set = true; deba@425: deba@425: for (NodeIt t(_graph); t != INVALID; ++t) { deba@425: if (reached[t]) continue; deba@425: _sets.push_front(std::list()); alpar@463: deba@427: queue[qlast++] = t; kpeter@628: reached[t] = true; deba@425: deba@427: while (qfirst != qlast) { deba@427: if (qsep == qfirst) { deba@427: ++bucket_num; deba@427: _sets.front().push_front(bucket_num); deba@427: _dormant[bucket_num] = !first_set; deba@427: _first[bucket_num] = _last[bucket_num] = INVALID; deba@427: qsep = qlast; deba@427: } deba@425: deba@427: Node n = queue[qfirst++]; deba@427: addItem(n, bucket_num); deba@427: deba@427: for (InArcIt a(_graph, n); a != INVALID; ++a) { deba@427: Node u = _graph.source(a); deba@427: if (!reached[u] && _tolerance.positive((*_capacity)[a])) { kpeter@628: reached[u] = true; deba@427: queue[qlast++] = u; deba@425: } deba@425: } deba@425: } deba@425: first_set = false; deba@425: } deba@425: deba@427: ++bucket_num; kpeter@628: (*_bucket)[_source] = 0; deba@425: _dormant[0] = true; deba@425: } kpeter@628: (*_source_set)[_source] = true; deba@425: deba@425: Node target = _last[_sets.back().back()]; deba@425: { deba@425: for (OutArcIt a(_graph, _source); a != INVALID; ++a) { deba@425: if (_tolerance.positive((*_capacity)[a])) { deba@425: Node u = _graph.target(a); kpeter@628: (*_flow)[a] = (*_capacity)[a]; kpeter@628: (*_excess)[u] += (*_capacity)[a]; deba@425: if (!(*_active)[u] && u != _source) { deba@425: activate(u); deba@425: } deba@425: } deba@425: } deba@425: deba@425: if ((*_active)[target]) { deba@425: deactivate(target); deba@425: } deba@425: deba@425: _highest = _sets.back().begin(); deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } deba@425: deba@425: while (true) { deba@425: while (_highest != _sets.back().end()) { deba@425: Node n = _first[*_highest]; deba@425: Value excess = (*_excess)[n]; deba@425: int next_bucket = _node_num; deba@425: deba@425: int under_bucket; deba@425: if (++std::list::iterator(_highest) == _sets.back().end()) { deba@425: under_bucket = -1; deba@425: } else { deba@425: under_bucket = *(++std::list::iterator(_highest)); deba@425: } deba@425: deba@425: for (OutArcIt a(_graph, n); a != INVALID; ++a) { deba@425: Node v = _graph.target(a); deba@425: if (_dormant[(*_bucket)[v]]) continue; deba@425: Value rem = (*_capacity)[a] - (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: if ((*_bucket)[v] == under_bucket) { deba@425: if (!(*_active)[v] && v != target) { deba@425: activate(v); deba@425: } deba@425: if (!_tolerance.less(rem, excess)) { kpeter@628: (*_flow)[a] += excess; kpeter@628: (*_excess)[v] += excess; deba@425: excess = 0; deba@425: goto no_more_push; deba@425: } else { deba@425: excess -= rem; kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = (*_capacity)[a]; deba@425: } deba@425: } else if (next_bucket > (*_bucket)[v]) { deba@425: next_bucket = (*_bucket)[v]; deba@425: } deba@425: } deba@425: deba@425: for (InArcIt a(_graph, n); a != INVALID; ++a) { deba@425: Node v = _graph.source(a); deba@425: if (_dormant[(*_bucket)[v]]) continue; deba@425: Value rem = (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: if ((*_bucket)[v] == under_bucket) { deba@425: if (!(*_active)[v] && v != target) { deba@425: activate(v); deba@425: } deba@425: if (!_tolerance.less(rem, excess)) { kpeter@628: (*_flow)[a] -= excess; kpeter@628: (*_excess)[v] += excess; deba@425: excess = 0; deba@425: goto no_more_push; deba@425: } else { deba@425: excess -= rem; kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = 0; deba@425: } deba@425: } else if (next_bucket > (*_bucket)[v]) { deba@425: next_bucket = (*_bucket)[v]; deba@425: } deba@425: } deba@425: deba@425: no_more_push: deba@425: kpeter@628: (*_excess)[n] = excess; deba@425: deba@425: if (excess != 0) { deba@425: if ((*_next)[n] == INVALID) { deba@425: typename std::list >::iterator new_set = deba@425: _sets.insert(--_sets.end(), std::list()); deba@425: new_set->splice(new_set->end(), _sets.back(), deba@425: _sets.back().begin(), ++_highest); deba@425: for (std::list::iterator it = new_set->begin(); deba@425: it != new_set->end(); ++it) { deba@425: _dormant[*it] = true; deba@425: } deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } else if (next_bucket == _node_num) { deba@425: _first[(*_bucket)[n]] = (*_next)[n]; kpeter@628: (*_prev)[(*_next)[n]] = INVALID; deba@425: deba@425: std::list >::iterator new_set = deba@425: _sets.insert(--_sets.end(), std::list()); deba@425: deba@425: new_set->push_front(bucket_num); kpeter@628: (*_bucket)[n] = bucket_num; deba@425: _first[bucket_num] = _last[bucket_num] = n; kpeter@628: (*_next)[n] = INVALID; kpeter@628: (*_prev)[n] = INVALID; deba@425: _dormant[bucket_num] = true; deba@425: ++bucket_num; deba@425: deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } else { deba@425: _first[*_highest] = (*_next)[n]; kpeter@628: (*_prev)[(*_next)[n]] = INVALID; deba@425: deba@425: while (next_bucket != *_highest) { deba@425: --_highest; deba@425: } deba@425: deba@425: if (_highest == _sets.back().begin()) { deba@425: _sets.back().push_front(bucket_num); deba@425: _dormant[bucket_num] = false; deba@425: _first[bucket_num] = _last[bucket_num] = INVALID; deba@425: ++bucket_num; deba@425: } deba@425: --_highest; deba@425: kpeter@628: (*_bucket)[n] = *_highest; kpeter@628: (*_next)[n] = _first[*_highest]; deba@425: if (_first[*_highest] != INVALID) { kpeter@628: (*_prev)[_first[*_highest]] = n; deba@425: } else { deba@425: _last[*_highest] = n; deba@425: } deba@425: _first[*_highest] = n; deba@425: } deba@425: } else { deba@425: deba@425: deactivate(n); deba@425: if (!(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: if (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: _highest = _sets.back().end(); deba@425: } deba@425: } deba@425: } deba@425: } deba@425: deba@425: if ((*_excess)[target] < _min_cut) { deba@425: _min_cut = (*_excess)[target]; deba@425: for (NodeIt i(_graph); i != INVALID; ++i) { kpeter@628: (*_min_cut_map)[i] = true; deba@425: } deba@425: for (std::list::iterator it = _sets.back().begin(); deba@425: it != _sets.back().end(); ++it) { deba@425: Node n = _first[*it]; deba@425: while (n != INVALID) { kpeter@628: (*_min_cut_map)[n] = false; deba@425: n = (*_next)[n]; deba@425: } deba@425: } deba@425: } deba@425: deba@425: { deba@425: Node new_target; deba@425: if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) { deba@425: if ((*_next)[target] == INVALID) { deba@425: _last[(*_bucket)[target]] = (*_prev)[target]; deba@425: new_target = (*_prev)[target]; deba@425: } else { kpeter@628: (*_prev)[(*_next)[target]] = (*_prev)[target]; deba@425: new_target = (*_next)[target]; deba@425: } deba@425: if ((*_prev)[target] == INVALID) { deba@425: _first[(*_bucket)[target]] = (*_next)[target]; deba@425: } else { kpeter@628: (*_next)[(*_prev)[target]] = (*_next)[target]; deba@425: } deba@425: } else { deba@425: _sets.back().pop_back(); deba@425: if (_sets.back().empty()) { deba@425: _sets.pop_back(); deba@425: if (_sets.empty()) deba@425: break; deba@425: for (std::list::iterator it = _sets.back().begin(); deba@425: it != _sets.back().end(); ++it) { deba@425: _dormant[*it] = false; deba@425: } deba@425: } deba@425: new_target = _last[_sets.back().back()]; deba@425: } deba@425: kpeter@628: (*_bucket)[target] = 0; deba@425: kpeter@628: (*_source_set)[target] = true; deba@425: for (OutArcIt a(_graph, target); a != INVALID; ++a) { deba@425: Value rem = (*_capacity)[a] - (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: Node v = _graph.target(a); deba@425: if (!(*_active)[v] && !(*_source_set)[v]) { deba@425: activate(v); deba@425: } kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = (*_capacity)[a]; deba@425: } deba@425: deba@425: for (InArcIt a(_graph, target); a != INVALID; ++a) { deba@425: Value rem = (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: Node v = _graph.source(a); deba@425: if (!(*_active)[v] && !(*_source_set)[v]) { deba@425: activate(v); deba@425: } kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = 0; deba@425: } deba@425: deba@425: target = new_target; deba@425: if ((*_active)[target]) { deba@425: deactivate(target); deba@425: } deba@425: deba@425: _highest = _sets.back().begin(); deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } deba@425: } deba@425: } deba@425: deba@425: void findMinCutIn() { deba@425: deba@425: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@628: (*_excess)[n] = 0; deba@644: (*_source_set)[n] = false; deba@425: } deba@425: deba@425: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@628: (*_flow)[a] = 0; deba@425: } deba@425: deba@427: int bucket_num = 0; deba@427: std::vector queue(_node_num); deba@427: int qfirst = 0, qlast = 0, qsep = 0; deba@425: deba@425: { deba@425: typename Digraph::template NodeMap reached(_graph, false); deba@425: kpeter@628: reached[_source] = true; deba@425: deba@425: bool first_set = true; deba@425: deba@425: for (NodeIt t(_graph); t != INVALID; ++t) { deba@425: if (reached[t]) continue; deba@425: _sets.push_front(std::list()); alpar@463: deba@427: queue[qlast++] = t; kpeter@628: reached[t] = true; deba@425: deba@427: while (qfirst != qlast) { deba@427: if (qsep == qfirst) { deba@427: ++bucket_num; deba@427: _sets.front().push_front(bucket_num); deba@427: _dormant[bucket_num] = !first_set; deba@427: _first[bucket_num] = _last[bucket_num] = INVALID; deba@427: qsep = qlast; deba@427: } deba@425: deba@427: Node n = queue[qfirst++]; deba@427: addItem(n, bucket_num); deba@427: deba@427: for (OutArcIt a(_graph, n); a != INVALID; ++a) { deba@427: Node u = _graph.target(a); deba@427: if (!reached[u] && _tolerance.positive((*_capacity)[a])) { kpeter@628: reached[u] = true; deba@427: queue[qlast++] = u; deba@425: } deba@425: } deba@425: } deba@425: first_set = false; deba@425: } deba@425: deba@427: ++bucket_num; kpeter@628: (*_bucket)[_source] = 0; deba@425: _dormant[0] = true; deba@425: } kpeter@628: (*_source_set)[_source] = true; deba@425: deba@425: Node target = _last[_sets.back().back()]; deba@425: { deba@425: for (InArcIt a(_graph, _source); a != INVALID; ++a) { deba@425: if (_tolerance.positive((*_capacity)[a])) { deba@425: Node u = _graph.source(a); kpeter@628: (*_flow)[a] = (*_capacity)[a]; kpeter@628: (*_excess)[u] += (*_capacity)[a]; deba@425: if (!(*_active)[u] && u != _source) { deba@425: activate(u); deba@425: } deba@425: } deba@425: } deba@425: if ((*_active)[target]) { deba@425: deactivate(target); deba@425: } deba@425: deba@425: _highest = _sets.back().begin(); deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } deba@425: deba@425: deba@425: while (true) { deba@425: while (_highest != _sets.back().end()) { deba@425: Node n = _first[*_highest]; deba@425: Value excess = (*_excess)[n]; deba@425: int next_bucket = _node_num; deba@425: deba@425: int under_bucket; deba@425: if (++std::list::iterator(_highest) == _sets.back().end()) { deba@425: under_bucket = -1; deba@425: } else { deba@425: under_bucket = *(++std::list::iterator(_highest)); deba@425: } deba@425: deba@425: for (InArcIt a(_graph, n); a != INVALID; ++a) { deba@425: Node v = _graph.source(a); deba@425: if (_dormant[(*_bucket)[v]]) continue; deba@425: Value rem = (*_capacity)[a] - (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: if ((*_bucket)[v] == under_bucket) { deba@425: if (!(*_active)[v] && v != target) { deba@425: activate(v); deba@425: } deba@425: if (!_tolerance.less(rem, excess)) { kpeter@628: (*_flow)[a] += excess; kpeter@628: (*_excess)[v] += excess; deba@425: excess = 0; deba@425: goto no_more_push; deba@425: } else { deba@425: excess -= rem; kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = (*_capacity)[a]; deba@425: } deba@425: } else if (next_bucket > (*_bucket)[v]) { deba@425: next_bucket = (*_bucket)[v]; deba@425: } deba@425: } deba@425: deba@425: for (OutArcIt a(_graph, n); a != INVALID; ++a) { deba@425: Node v = _graph.target(a); deba@425: if (_dormant[(*_bucket)[v]]) continue; deba@425: Value rem = (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: if ((*_bucket)[v] == under_bucket) { deba@425: if (!(*_active)[v] && v != target) { deba@425: activate(v); deba@425: } deba@425: if (!_tolerance.less(rem, excess)) { kpeter@628: (*_flow)[a] -= excess; kpeter@628: (*_excess)[v] += excess; deba@425: excess = 0; deba@425: goto no_more_push; deba@425: } else { deba@425: excess -= rem; kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = 0; deba@425: } deba@425: } else if (next_bucket > (*_bucket)[v]) { deba@425: next_bucket = (*_bucket)[v]; deba@425: } deba@425: } deba@425: deba@425: no_more_push: deba@425: kpeter@628: (*_excess)[n] = excess; deba@425: deba@425: if (excess != 0) { deba@425: if ((*_next)[n] == INVALID) { deba@425: typename std::list >::iterator new_set = deba@425: _sets.insert(--_sets.end(), std::list()); deba@425: new_set->splice(new_set->end(), _sets.back(), deba@425: _sets.back().begin(), ++_highest); deba@425: for (std::list::iterator it = new_set->begin(); deba@425: it != new_set->end(); ++it) { deba@425: _dormant[*it] = true; deba@425: } deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } else if (next_bucket == _node_num) { deba@425: _first[(*_bucket)[n]] = (*_next)[n]; kpeter@628: (*_prev)[(*_next)[n]] = INVALID; deba@425: deba@425: std::list >::iterator new_set = deba@425: _sets.insert(--_sets.end(), std::list()); deba@425: deba@425: new_set->push_front(bucket_num); kpeter@628: (*_bucket)[n] = bucket_num; deba@425: _first[bucket_num] = _last[bucket_num] = n; kpeter@628: (*_next)[n] = INVALID; kpeter@628: (*_prev)[n] = INVALID; deba@425: _dormant[bucket_num] = true; deba@425: ++bucket_num; deba@425: deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } else { deba@425: _first[*_highest] = (*_next)[n]; kpeter@628: (*_prev)[(*_next)[n]] = INVALID; deba@425: deba@425: while (next_bucket != *_highest) { deba@425: --_highest; deba@425: } deba@425: if (_highest == _sets.back().begin()) { deba@425: _sets.back().push_front(bucket_num); deba@425: _dormant[bucket_num] = false; deba@425: _first[bucket_num] = _last[bucket_num] = INVALID; deba@425: ++bucket_num; deba@425: } deba@425: --_highest; deba@425: kpeter@628: (*_bucket)[n] = *_highest; kpeter@628: (*_next)[n] = _first[*_highest]; deba@425: if (_first[*_highest] != INVALID) { kpeter@628: (*_prev)[_first[*_highest]] = n; deba@425: } else { deba@425: _last[*_highest] = n; deba@425: } deba@425: _first[*_highest] = n; deba@425: } deba@425: } else { deba@425: deba@425: deactivate(n); deba@425: if (!(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: if (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: _highest = _sets.back().end(); deba@425: } deba@425: } deba@425: } deba@425: } deba@425: deba@425: if ((*_excess)[target] < _min_cut) { deba@425: _min_cut = (*_excess)[target]; deba@425: for (NodeIt i(_graph); i != INVALID; ++i) { kpeter@628: (*_min_cut_map)[i] = false; deba@425: } deba@425: for (std::list::iterator it = _sets.back().begin(); deba@425: it != _sets.back().end(); ++it) { deba@425: Node n = _first[*it]; deba@425: while (n != INVALID) { kpeter@628: (*_min_cut_map)[n] = true; deba@425: n = (*_next)[n]; deba@425: } deba@425: } deba@425: } deba@425: deba@425: { deba@425: Node new_target; deba@425: if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) { deba@425: if ((*_next)[target] == INVALID) { deba@425: _last[(*_bucket)[target]] = (*_prev)[target]; deba@425: new_target = (*_prev)[target]; deba@425: } else { kpeter@628: (*_prev)[(*_next)[target]] = (*_prev)[target]; deba@425: new_target = (*_next)[target]; deba@425: } deba@425: if ((*_prev)[target] == INVALID) { deba@425: _first[(*_bucket)[target]] = (*_next)[target]; deba@425: } else { kpeter@628: (*_next)[(*_prev)[target]] = (*_next)[target]; deba@425: } deba@425: } else { deba@425: _sets.back().pop_back(); deba@425: if (_sets.back().empty()) { deba@425: _sets.pop_back(); deba@425: if (_sets.empty()) deba@425: break; deba@425: for (std::list::iterator it = _sets.back().begin(); deba@425: it != _sets.back().end(); ++it) { deba@425: _dormant[*it] = false; deba@425: } deba@425: } deba@425: new_target = _last[_sets.back().back()]; deba@425: } deba@425: kpeter@628: (*_bucket)[target] = 0; deba@425: kpeter@628: (*_source_set)[target] = true; deba@425: for (InArcIt a(_graph, target); a != INVALID; ++a) { deba@425: Value rem = (*_capacity)[a] - (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: Node v = _graph.source(a); deba@425: if (!(*_active)[v] && !(*_source_set)[v]) { deba@425: activate(v); deba@425: } kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = (*_capacity)[a]; deba@425: } deba@425: deba@425: for (OutArcIt a(_graph, target); a != INVALID; ++a) { deba@425: Value rem = (*_flow)[a]; deba@425: if (!_tolerance.positive(rem)) continue; deba@425: Node v = _graph.target(a); deba@425: if (!(*_active)[v] && !(*_source_set)[v]) { deba@425: activate(v); deba@425: } kpeter@628: (*_excess)[v] += rem; kpeter@628: (*_flow)[a] = 0; deba@425: } deba@425: deba@425: target = new_target; deba@425: if ((*_active)[target]) { deba@425: deactivate(target); deba@425: } deba@425: deba@425: _highest = _sets.back().begin(); deba@425: while (_highest != _sets.back().end() && deba@425: !(*_active)[_first[*_highest]]) { deba@425: ++_highest; deba@425: } deba@425: } deba@425: } deba@425: } deba@425: deba@425: public: deba@425: kpeter@643: /// \name Execution Control deba@425: /// The simplest way to execute the algorithm is to use kpeter@606: /// one of the member functions called \ref run(). deba@425: /// \n kpeter@643: /// If you need better control on the execution, kpeter@643: /// you have to call one of the \ref init() functions first, then kpeter@643: /// \ref calculateOut() and/or \ref calculateIn(). deba@425: deba@425: /// @{ deba@425: kpeter@643: /// \brief Initialize the internal data structures. deba@425: /// kpeter@643: /// This function initializes the internal data structures. It creates kpeter@643: /// the maps and some bucket structures for the algorithm. kpeter@643: /// The first node is used as the source node for the push-relabel kpeter@643: /// algorithm. deba@425: void init() { deba@425: init(NodeIt(_graph)); deba@425: } deba@425: kpeter@643: /// \brief Initialize the internal data structures. deba@425: /// kpeter@643: /// This function initializes the internal data structures. It creates kpeter@643: /// the maps and some bucket structures for the algorithm. kpeter@643: /// The given node is used as the source node for the push-relabel kpeter@643: /// algorithm. deba@425: void init(const Node& source) { deba@425: _source = source; deba@425: deba@425: _node_num = countNodes(_graph); deba@425: deba@427: _first.resize(_node_num); deba@427: _last.resize(_node_num); deba@425: deba@427: _dormant.resize(_node_num); deba@425: deba@425: if (!_flow) { deba@425: _flow = new FlowMap(_graph); deba@425: } deba@425: if (!_next) { deba@425: _next = new typename Digraph::template NodeMap(_graph); deba@425: } deba@425: if (!_prev) { deba@425: _prev = new typename Digraph::template NodeMap(_graph); deba@425: } deba@425: if (!_active) { deba@425: _active = new typename Digraph::template NodeMap(_graph); deba@425: } deba@425: if (!_bucket) { deba@425: _bucket = new typename Digraph::template NodeMap(_graph); deba@425: } deba@425: if (!_excess) { deba@425: _excess = new ExcessMap(_graph); deba@425: } deba@425: if (!_source_set) { deba@425: _source_set = new SourceSetMap(_graph); deba@425: } deba@425: if (!_min_cut_map) { deba@425: _min_cut_map = new MinCutMap(_graph); deba@425: } deba@425: deba@425: _min_cut = std::numeric_limits::max(); deba@425: } deba@425: deba@425: kpeter@643: /// \brief Calculate a minimum cut with \f$ source \f$ on the deba@425: /// source-side. deba@425: /// kpeter@643: /// This function calculates a minimum cut with \f$ source \f$ on the alpar@428: /// source-side (i.e. a set \f$ X\subsetneq V \f$ with kpeter@643: /// \f$ source \in X \f$ and minimal outgoing capacity). kpeter@643: /// kpeter@643: /// \pre \ref init() must be called before using this function. deba@425: void calculateOut() { deba@425: findMinCutOut(); deba@425: } deba@425: kpeter@643: /// \brief Calculate a minimum cut with \f$ source \f$ on the kpeter@643: /// sink-side. deba@425: /// kpeter@643: /// This function calculates a minimum cut with \f$ source \f$ on the kpeter@643: /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with kpeter@643: /// \f$ source \notin X \f$ and minimal outgoing capacity). kpeter@643: /// kpeter@643: /// \pre \ref init() must be called before using this function. deba@425: void calculateIn() { deba@425: findMinCutIn(); deba@425: } deba@425: deba@425: kpeter@643: /// \brief Run the algorithm. deba@425: /// kpeter@643: /// This function runs the algorithm. It finds nodes \c source and kpeter@643: /// \c target arbitrarily and then calls \ref init(), \ref calculateOut() deba@425: /// and \ref calculateIn(). deba@425: void run() { deba@425: init(); deba@425: calculateOut(); deba@425: calculateIn(); deba@425: } deba@425: kpeter@643: /// \brief Run the algorithm. deba@425: /// kpeter@643: /// This function runs the algorithm. It uses the given \c source node, kpeter@643: /// finds a proper \c target node and then calls the \ref init(), kpeter@643: /// \ref calculateOut() and \ref calculateIn(). deba@425: void run(const Node& s) { deba@425: init(s); deba@425: calculateOut(); deba@425: calculateIn(); deba@425: } deba@425: deba@425: /// @} deba@425: deba@425: /// \name Query Functions deba@425: /// The result of the %HaoOrlin algorithm kpeter@643: /// can be obtained using these functions.\n kpeter@643: /// \ref run(), \ref calculateOut() or \ref calculateIn() kpeter@643: /// should be called before using them. deba@425: deba@425: /// @{ deba@425: kpeter@643: /// \brief Return the value of the minimum cut. deba@425: /// kpeter@643: /// This function returns the value of the minimum cut. kpeter@643: /// kpeter@643: /// \pre \ref run(), \ref calculateOut() or \ref calculateIn() kpeter@643: /// must be called before using this function. deba@425: Value minCutValue() const { deba@425: return _min_cut; deba@425: } deba@425: deba@425: kpeter@643: /// \brief Return a minimum cut. deba@425: /// kpeter@643: /// This function sets \c cutMap to the characteristic vector of a kpeter@643: /// minimum value cut: it will give a non-empty set \f$ X\subsetneq V \f$ kpeter@643: /// with minimal outgoing capacity (i.e. \c cutMap will be \c true exactly kpeter@643: /// for the nodes of \f$ X \f$). kpeter@643: /// kpeter@643: /// \param cutMap A \ref concepts::WriteMap "writable" node map with kpeter@643: /// \c bool (or convertible) value type. kpeter@643: /// kpeter@643: /// \return The value of the minimum cut. kpeter@643: /// kpeter@643: /// \pre \ref run(), \ref calculateOut() or \ref calculateIn() kpeter@643: /// must be called before using this function. kpeter@643: template kpeter@643: Value minCutMap(CutMap& cutMap) const { deba@425: for (NodeIt it(_graph); it != INVALID; ++it) { kpeter@643: cutMap.set(it, (*_min_cut_map)[it]); deba@425: } deba@425: return _min_cut; deba@425: } deba@425: deba@425: /// @} deba@425: deba@425: }; //class HaoOrlin deba@425: deba@425: } //namespace lemon deba@425: deba@425: #endif //LEMON_HAO_ORLIN_H