3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_GOMORY_HU_TREE_H
20 #define LEMON_GOMORY_HU_TREE_H
22 #include <lemon/preflow.h>
23 #include <lemon/concept_check.h>
24 #include <lemon/concepts/maps.h>
28 /// \brief Gomory-Hu cut tree in undirected graphs.
34 /// \brief Gomory-Hu cut tree algorithm
36 /// The Gomory-Hu tree is a tree on the nodeset of the graph, but it
37 /// may contain edges which are not in the original graph. It helps
38 /// to calculate the minimum cut between all pairs of nodes, because
39 /// the minimum capacity edge on the tree path between two nodes has
40 /// the same weight as the minimum cut in the graph between these
41 /// nodes. Moreover this edge separates the nodes to two parts which
42 /// determine this minimum cut.
44 /// The algorithm calculates \e n-1 distinict minimum cuts with
45 /// preflow algorithm, therefore the algorithm has
46 /// \f$(O(n^3\sqrt{e})\f$ overall time complexity. It calculates a
47 /// rooted Gomory-Hu tree, the structure of the tree and the weights
48 /// can be obtained with \c predNode() and \c predValue()
49 /// functions. The \c minCutValue() and \c minCutMap() calculates
50 /// the minimum cut and the minimum cut value between any two node
52 template <typename _UGraph,
53 typename _Capacity = typename _UGraph::template UEdgeMap<int> >
57 /// The undirected graph type
58 typedef _UGraph UGraph;
59 /// The capacity on undirected edges
60 typedef _Capacity Capacity;
61 /// The value type of capacities
62 typedef typename Capacity::Value Value;
66 UGRAPH_TYPEDEFS(typename UGraph);
68 const UGraph& _ugraph;
69 const Capacity& _capacity;
72 typename UGraph::template NodeMap<Node>* _pred;
73 typename UGraph::template NodeMap<Value>* _weight;
74 typename UGraph::template NodeMap<int>* _order;
76 void createStructures() {
78 _pred = new typename UGraph::template NodeMap<Node>(_ugraph);
81 _weight = new typename UGraph::template NodeMap<Value>(_ugraph);
84 _order = new typename UGraph::template NodeMap<int>(_ugraph);
88 void destroyStructures() {
102 /// \brief Constructor
105 /// \param ugraph The undirected graph type.
106 /// \param capacity The capacity map.
107 GomoryHuTree(const UGraph& ugraph, const Capacity& capacity)
108 : _ugraph(ugraph), _capacity(capacity),
109 _pred(0), _weight(0), _order(0)
111 checkConcept<concepts::ReadMap<UEdge, Value>, Capacity>();
115 /// \brief Destructor
122 /// \brief Initializes the internal data structures.
124 /// Initializes the internal data structures.
129 _root = NodeIt(_ugraph);
130 for (NodeIt n(_ugraph); n != INVALID; ++n) {
131 _pred->set(n, _root);
134 _pred->set(_root, INVALID);
135 _weight->set(_root, std::numeric_limits<Value>::max());
139 /// \brief Starts the algorithm
141 /// Starts the algorithm.
143 Preflow<UGraph, Capacity> fa(_ugraph, _capacity, _root, INVALID);
145 for (NodeIt n(_ugraph); n != INVALID; ++n) {
146 if (n == _root) continue;
148 Node pn = (*_pred)[n];
154 _weight->set(n, fa.flowValue());
156 for (NodeIt nn(_ugraph); nn != INVALID; ++nn) {
157 if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
161 if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
162 _pred->set(n, (*_pred)[pn]);
164 _weight->set(n, (*_weight)[pn]);
165 _weight->set(pn, fa.flowValue());
169 _order->set(_root, 0);
172 for (NodeIt n(_ugraph); n != INVALID; ++n) {
173 std::vector<Node> st;
175 while ((*_order)[nn] == -1) {
179 while (!st.empty()) {
180 _order->set(st.back(), index++);
186 /// \brief Runs the Gomory-Hu algorithm.
188 /// Runs the Gomory-Hu algorithm.
189 /// \note gh.run() is just a shortcut of the following code.
199 /// \brief Returns the predecessor node in the Gomory-Hu tree.
201 /// Returns the predecessor node in the Gomory-Hu tree. If the node is
202 /// the root of the Gomory-Hu tree, then it returns \c INVALID.
203 Node predNode(const Node& node) {
204 return (*_pred)[node];
207 /// \brief Returns the weight of the predecessor edge in the
210 /// Returns the weight of the predecessor edge in the Gomory-Hu
211 /// tree. If the node is the root of the Gomory-Hu tree, the
212 /// result is undefined.
213 Value predValue(const Node& node) {
214 return (*_weight)[node];
217 /// \brief Returns the minimum cut value between two nodes
219 /// Returns the minimum cut value between two nodes. The
220 /// algorithm finds the nearest common ancestor in the Gomory-Hu
221 /// tree and calculates the minimum weight edge on the paths to
223 Value minCutValue(const Node& s, const Node& t) const {
225 Value value = std::numeric_limits<Value>::max();
228 if ((*_order)[sn] < (*_order)[tn]) {
229 if ((*_weight)[tn] < value) value = (*_weight)[tn];
232 if ((*_weight)[sn] < value) value = (*_weight)[sn];
239 /// \brief Returns the minimum cut between two nodes
241 /// Returns the minimum cut value between two nodes. The
242 /// algorithm finds the nearest common ancestor in the Gomory-Hu
243 /// tree and calculates the minimum weight edge on the paths to
244 /// the ancestor. Then it sets all nodes to the cut determined by
245 /// this edge. The \c cutMap should be \ref concepts::ReadWriteMap
247 template <typename CutMap>
248 Value minCutMap(const Node& s, const Node& t, CutMap& cutMap) const {
252 Value value = std::numeric_limits<Value>::max();
255 if ((*_order)[sn] < (*_order)[tn]) {
256 if ((*_weight)[tn] < value) {
258 value = (*_weight)[tn];
262 if ((*_weight)[sn] < value) {
264 value = (*_weight)[sn];
270 typename UGraph::template NodeMap<bool> reached(_ugraph, false);
271 reached.set(_root, true);
272 cutMap.set(_root, false);
273 reached.set(rn, true);
274 cutMap.set(rn, true);
276 for (NodeIt n(_ugraph); n != INVALID; ++n) {
277 std::vector<Node> st;
279 while (!reached[nn]) {
283 while (!st.empty()) {
284 cutMap.set(st.back(), cutMap[nn]);