lemon/gomory_hu_tree.h
author Janos Tapolcai <tapolcai@tmit.bme.hu>
Fri, 20 Feb 2009 17:17:17 +0100
changeset 531 924887566bf2
child 532 ccd2d3a3001e
permissions -rw-r--r--
Porting Gomory-Hu algorithm (#66)
tapolcai@531
     1
/* -*- C++ -*-
tapolcai@531
     2
 *
tapolcai@531
     3
 * This file is a part of LEMON, a generic C++ optimization library
tapolcai@531
     4
 *
tapolcai@531
     5
 * Copyright (C) 2003-2008
tapolcai@531
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
tapolcai@531
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
tapolcai@531
     8
 *
tapolcai@531
     9
 * Permission to use, modify and distribute this software is granted
tapolcai@531
    10
 * provided that this copyright notice appears in all copies. For
tapolcai@531
    11
 * precise terms see the accompanying LICENSE file.
tapolcai@531
    12
 *
tapolcai@531
    13
 * This software is provided "AS IS" with no warranty of any kind,
tapolcai@531
    14
 * express or implied, and with no claim as to its suitability for any
tapolcai@531
    15
 * purpose.
tapolcai@531
    16
 *
tapolcai@531
    17
 */
tapolcai@531
    18
tapolcai@531
    19
#ifndef LEMON_GOMORY_HU_TREE_H
tapolcai@531
    20
#define LEMON_GOMORY_HU_TREE_H
tapolcai@531
    21
tapolcai@531
    22
#include <limits>
tapolcai@531
    23
tapolcai@531
    24
#include <lemon/preflow.h>
tapolcai@531
    25
#include <lemon/concept_check.h>
tapolcai@531
    26
#include <lemon/concepts/maps.h>
tapolcai@531
    27
tapolcai@531
    28
/// \ingroup min_cut
tapolcai@531
    29
/// \file 
tapolcai@531
    30
/// \brief Gomory-Hu cut tree in graphs.
tapolcai@531
    31
tapolcai@531
    32
namespace lemon {
tapolcai@531
    33
tapolcai@531
    34
  /// \ingroup min_cut
tapolcai@531
    35
  ///
tapolcai@531
    36
  /// \brief Gomory-Hu cut tree algorithm
tapolcai@531
    37
  ///
tapolcai@531
    38
  /// The Gomory-Hu tree is a tree on the nodeset of the digraph, but it
tapolcai@531
    39
  /// may contain arcs which are not in the original digraph. It helps
tapolcai@531
    40
  /// to calculate the minimum cut between all pairs of nodes, because
tapolcai@531
    41
  /// the minimum capacity arc on the tree path between two nodes has
tapolcai@531
    42
  /// the same weight as the minimum cut in the digraph between these
tapolcai@531
    43
  /// nodes. Moreover this arc separates the nodes to two parts which
tapolcai@531
    44
  /// determine this minimum cut.
tapolcai@531
    45
  /// 
tapolcai@531
    46
  /// The algorithm calculates \e n-1 distinict minimum cuts with
tapolcai@531
    47
  /// preflow algorithm, therefore the algorithm has
tapolcai@531
    48
  /// \f$(O(n^3\sqrt{e})\f$ overall time complexity. It calculates a
tapolcai@531
    49
  /// rooted Gomory-Hu tree, the structure of the tree and the weights
tapolcai@531
    50
  /// can be obtained with \c predNode() and \c predValue()
tapolcai@531
    51
  /// functions. The \c minCutValue() and \c minCutMap() calculates
tapolcai@531
    52
  /// the minimum cut and the minimum cut value between any two node
tapolcai@531
    53
  /// in the digraph.
tapolcai@531
    54
  template <typename _Graph, 
tapolcai@531
    55
	    typename _Capacity = typename _Graph::template EdgeMap<int> >
tapolcai@531
    56
  class GomoryHuTree {
tapolcai@531
    57
  public:
tapolcai@531
    58
tapolcai@531
    59
    /// The graph type
tapolcai@531
    60
    typedef _Graph Graph;
tapolcai@531
    61
    /// The capacity on edges
tapolcai@531
    62
    typedef _Capacity Capacity;
tapolcai@531
    63
    /// The value type of capacities
tapolcai@531
    64
    typedef typename Capacity::Value Value;
tapolcai@531
    65
    
tapolcai@531
    66
  private:
tapolcai@531
    67
tapolcai@531
    68
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
tapolcai@531
    69
tapolcai@531
    70
    const Graph& _graph;
tapolcai@531
    71
    const Capacity& _capacity;
tapolcai@531
    72
tapolcai@531
    73
    Node _root;
tapolcai@531
    74
    typename Graph::template NodeMap<Node>* _pred;
tapolcai@531
    75
    typename Graph::template NodeMap<Value>* _weight;
tapolcai@531
    76
    typename Graph::template NodeMap<int>* _order;
tapolcai@531
    77
tapolcai@531
    78
    void createStructures() {
tapolcai@531
    79
      if (!_pred) {
tapolcai@531
    80
	_pred = new typename Graph::template NodeMap<Node>(_graph);
tapolcai@531
    81
      }
tapolcai@531
    82
      if (!_weight) {
tapolcai@531
    83
	_weight = new typename Graph::template NodeMap<Value>(_graph);
tapolcai@531
    84
      }
tapolcai@531
    85
      if (!_order) {
tapolcai@531
    86
	_order = new typename Graph::template NodeMap<int>(_graph);
tapolcai@531
    87
      }
tapolcai@531
    88
    }
tapolcai@531
    89
tapolcai@531
    90
    void destroyStructures() {
tapolcai@531
    91
      if (_pred) {
tapolcai@531
    92
	delete _pred;
tapolcai@531
    93
      }
tapolcai@531
    94
      if (_weight) {
tapolcai@531
    95
	delete _weight;
tapolcai@531
    96
      }
tapolcai@531
    97
      if (_order) {
tapolcai@531
    98
	delete _order;
tapolcai@531
    99
      }
tapolcai@531
   100
    }
tapolcai@531
   101
  
tapolcai@531
   102
  public:
tapolcai@531
   103
tapolcai@531
   104
    /// \brief Constructor
tapolcai@531
   105
    ///
tapolcai@531
   106
    /// Constructor
tapolcai@531
   107
    /// \param graph The graph type.
tapolcai@531
   108
    /// \param capacity The capacity map.
tapolcai@531
   109
    GomoryHuTree(const Graph& graph, const Capacity& capacity) 
tapolcai@531
   110
      : _graph(graph), _capacity(capacity),
tapolcai@531
   111
	_pred(0), _weight(0), _order(0) 
tapolcai@531
   112
    {
tapolcai@531
   113
      checkConcept<concepts::ReadMap<Edge, Value>, Capacity>();
tapolcai@531
   114
    }
tapolcai@531
   115
tapolcai@531
   116
tapolcai@531
   117
    /// \brief Destructor
tapolcai@531
   118
    ///
tapolcai@531
   119
    /// Destructor
tapolcai@531
   120
    ~GomoryHuTree() {
tapolcai@531
   121
      destroyStructures();
tapolcai@531
   122
    }
tapolcai@531
   123
tapolcai@531
   124
    /// \brief Initializes the internal data structures.
tapolcai@531
   125
    ///
tapolcai@531
   126
    /// Initializes the internal data structures.
tapolcai@531
   127
    ///
tapolcai@531
   128
    void init() {
tapolcai@531
   129
      createStructures();
tapolcai@531
   130
tapolcai@531
   131
      _root = NodeIt(_graph);
tapolcai@531
   132
      for (NodeIt n(_graph); n != INVALID; ++n) {
tapolcai@531
   133
	_pred->set(n, _root);
tapolcai@531
   134
	_order->set(n, -1);
tapolcai@531
   135
      }
tapolcai@531
   136
      _pred->set(_root, INVALID);
tapolcai@531
   137
      _weight->set(_root, std::numeric_limits<Value>::max()); 
tapolcai@531
   138
    }
tapolcai@531
   139
tapolcai@531
   140
tapolcai@531
   141
    /// \brief Starts the algorithm
tapolcai@531
   142
    ///
tapolcai@531
   143
    /// Starts the algorithm.
tapolcai@531
   144
    void start() {
tapolcai@531
   145
      Preflow<Graph, Capacity> fa(_graph, _capacity, _root, INVALID);
tapolcai@531
   146
tapolcai@531
   147
      for (NodeIt n(_graph); n != INVALID; ++n) {
tapolcai@531
   148
	if (n == _root) continue;
tapolcai@531
   149
tapolcai@531
   150
	Node pn = (*_pred)[n];
tapolcai@531
   151
	fa.source(n);
tapolcai@531
   152
	fa.target(pn);
tapolcai@531
   153
tapolcai@531
   154
	fa.runMinCut();
tapolcai@531
   155
tapolcai@531
   156
	_weight->set(n, fa.flowValue());
tapolcai@531
   157
tapolcai@531
   158
	for (NodeIt nn(_graph); nn != INVALID; ++nn) {
tapolcai@531
   159
	  if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
tapolcai@531
   160
	    _pred->set(nn, n);
tapolcai@531
   161
	  }
tapolcai@531
   162
	}
tapolcai@531
   163
	if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
tapolcai@531
   164
	  _pred->set(n, (*_pred)[pn]);
tapolcai@531
   165
	  _pred->set(pn, n);
tapolcai@531
   166
	  _weight->set(n, (*_weight)[pn]);
tapolcai@531
   167
	  _weight->set(pn, fa.flowValue());	
tapolcai@531
   168
	}
tapolcai@531
   169
      }
tapolcai@531
   170
tapolcai@531
   171
      _order->set(_root, 0);
tapolcai@531
   172
      int index = 1;
tapolcai@531
   173
tapolcai@531
   174
      for (NodeIt n(_graph); n != INVALID; ++n) {
tapolcai@531
   175
	std::vector<Node> st;
tapolcai@531
   176
	Node nn = n;
tapolcai@531
   177
	while ((*_order)[nn] == -1) {
tapolcai@531
   178
	  st.push_back(nn);
tapolcai@531
   179
	  nn = (*_pred)[nn];
tapolcai@531
   180
	}
tapolcai@531
   181
	while (!st.empty()) {
tapolcai@531
   182
	  _order->set(st.back(), index++);
tapolcai@531
   183
	  st.pop_back();
tapolcai@531
   184
	}
tapolcai@531
   185
      }
tapolcai@531
   186
    }
tapolcai@531
   187
tapolcai@531
   188
    /// \brief Runs the Gomory-Hu algorithm.  
tapolcai@531
   189
    ///
tapolcai@531
   190
    /// Runs the Gomory-Hu algorithm.
tapolcai@531
   191
    /// \note gh.run() is just a shortcut of the following code.
tapolcai@531
   192
    /// \code
tapolcai@531
   193
    ///   ght.init();
tapolcai@531
   194
    ///   ght.start();
tapolcai@531
   195
    /// \endcode
tapolcai@531
   196
    void run() {
tapolcai@531
   197
      init();
tapolcai@531
   198
      start();
tapolcai@531
   199
    }
tapolcai@531
   200
tapolcai@531
   201
    /// \brief Returns the predecessor node in the Gomory-Hu tree.
tapolcai@531
   202
    ///
tapolcai@531
   203
    /// Returns the predecessor node in the Gomory-Hu tree. If the node is
tapolcai@531
   204
    /// the root of the Gomory-Hu tree, then it returns \c INVALID.
tapolcai@531
   205
    Node predNode(const Node& node) {
tapolcai@531
   206
      return (*_pred)[node];
tapolcai@531
   207
    }
tapolcai@531
   208
tapolcai@531
   209
    /// \brief Returns the weight of the predecessor arc in the
tapolcai@531
   210
    /// Gomory-Hu tree.
tapolcai@531
   211
    ///
tapolcai@531
   212
    /// Returns the weight of the predecessor arc in the Gomory-Hu
tapolcai@531
   213
    /// tree.  If the node is the root of the Gomory-Hu tree, the
tapolcai@531
   214
    /// result is undefined.
tapolcai@531
   215
    Value predValue(const Node& node) {
tapolcai@531
   216
      return (*_weight)[node];
tapolcai@531
   217
    }
tapolcai@531
   218
tapolcai@531
   219
    /// \brief Returns the minimum cut value between two nodes
tapolcai@531
   220
    ///
tapolcai@531
   221
    /// Returns the minimum cut value between two nodes. The
tapolcai@531
   222
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
tapolcai@531
   223
    /// tree and calculates the minimum weight arc on the paths to
tapolcai@531
   224
    /// the ancestor.
tapolcai@531
   225
    Value minCutValue(const Node& s, const Node& t) const {
tapolcai@531
   226
      Node sn = s, tn = t;
tapolcai@531
   227
      Value value = std::numeric_limits<Value>::max();
tapolcai@531
   228
      
tapolcai@531
   229
      while (sn != tn) {
tapolcai@531
   230
	if ((*_order)[sn] < (*_order)[tn]) {
tapolcai@531
   231
	  if ((*_weight)[tn] < value) value = (*_weight)[tn];
tapolcai@531
   232
	  tn = (*_pred)[tn];
tapolcai@531
   233
	} else {
tapolcai@531
   234
	  if ((*_weight)[sn] < value) value = (*_weight)[sn];
tapolcai@531
   235
	  sn = (*_pred)[sn];
tapolcai@531
   236
	}
tapolcai@531
   237
      }
tapolcai@531
   238
      return value;
tapolcai@531
   239
    }
tapolcai@531
   240
tapolcai@531
   241
    /// \brief Returns the minimum cut between two nodes
tapolcai@531
   242
    ///
tapolcai@531
   243
    /// Returns the minimum cut value between two nodes. The
tapolcai@531
   244
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
tapolcai@531
   245
    /// tree and calculates the minimum weight arc on the paths to
tapolcai@531
   246
    /// the ancestor. Then it sets all nodes to the cut determined by
tapolcai@531
   247
    /// this arc. The \c cutMap should be \ref concepts::ReadWriteMap
tapolcai@531
   248
    /// "ReadWriteMap".
tapolcai@531
   249
    template <typename CutMap>
tapolcai@531
   250
    Value minCutMap(const Node& s, const Node& t, CutMap& cutMap) const {
tapolcai@531
   251
      Node sn = s, tn = t;
tapolcai@531
   252
tapolcai@531
   253
      Node rn = INVALID;
tapolcai@531
   254
      Value value = std::numeric_limits<Value>::max();
tapolcai@531
   255
      
tapolcai@531
   256
      while (sn != tn) {
tapolcai@531
   257
	if ((*_order)[sn] < (*_order)[tn]) {
tapolcai@531
   258
	  if ((*_weight)[tn] < value) {
tapolcai@531
   259
	    rn = tn;
tapolcai@531
   260
	    value = (*_weight)[tn];
tapolcai@531
   261
	  }
tapolcai@531
   262
	  tn = (*_pred)[tn];
tapolcai@531
   263
	} else {
tapolcai@531
   264
	  if ((*_weight)[sn] < value) {
tapolcai@531
   265
	    rn = sn;
tapolcai@531
   266
	    value = (*_weight)[sn];
tapolcai@531
   267
	  }
tapolcai@531
   268
	  sn = (*_pred)[sn];
tapolcai@531
   269
	}
tapolcai@531
   270
      }
tapolcai@531
   271
tapolcai@531
   272
      typename Graph::template NodeMap<bool> reached(_graph, false);
tapolcai@531
   273
      reached.set(_root, true);
tapolcai@531
   274
      cutMap.set(_root, false);
tapolcai@531
   275
      reached.set(rn, true);
tapolcai@531
   276
      cutMap.set(rn, true);
tapolcai@531
   277
tapolcai@531
   278
      for (NodeIt n(_graph); n != INVALID; ++n) {
tapolcai@531
   279
	std::vector<Node> st;
tapolcai@531
   280
	Node nn = n;
tapolcai@531
   281
	while (!reached[nn]) {
tapolcai@531
   282
	  st.push_back(nn);
tapolcai@531
   283
	  nn = (*_pred)[nn];
tapolcai@531
   284
	}
tapolcai@531
   285
	while (!st.empty()) {
tapolcai@531
   286
	  cutMap.set(st.back(), cutMap[nn]);
tapolcai@531
   287
	  st.pop_back();
tapolcai@531
   288
	}
tapolcai@531
   289
      }
tapolcai@531
   290
      
tapolcai@531
   291
      return value;
tapolcai@531
   292
    }
tapolcai@531
   293
tapolcai@531
   294
  };
tapolcai@531
   295
tapolcai@531
   296
}
tapolcai@531
   297
tapolcai@531
   298
#endif