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