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