src/lemon/kruskal.h
author alpar
Fri, 18 Mar 2005 06:00:20 +0000
changeset 1226 71fcebd3a041
parent 987 87f7c54892df
child 1274 5676e48ca026
permissions -rw-r--r--
Minor changes for educational purposes.
(Much more would be necessary...)
alpar@906
     1
/* -*- C++ -*-
alpar@921
     2
 * src/lemon/kruskal.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@906
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@906
    16
alpar@921
    17
#ifndef LEMON_KRUSKAL_H
alpar@921
    18
#define LEMON_KRUSKAL_H
alpar@810
    19
alpar@810
    20
#include <algorithm>
alpar@921
    21
#include <lemon/unionfind.h>
alpar@810
    22
alpar@810
    23
/**
alpar@810
    24
@defgroup spantree Minimum Cost Spanning Tree Algorithms
alpar@810
    25
@ingroup galgs
alpar@810
    26
\brief This group containes the algorithms for finding a minimum cost spanning
alpar@810
    27
tree in a graph
alpar@810
    28
alpar@810
    29
This group containes the algorithms for finding a minimum cost spanning
alpar@810
    30
tree in a graph
alpar@810
    31
*/
alpar@810
    32
alpar@810
    33
///\ingroup spantree
alpar@810
    34
///\file
alpar@810
    35
///\brief Kruskal's algorithm to compute a minimum cost tree
alpar@810
    36
///
alpar@810
    37
///Kruskal's algorithm to compute a minimum cost tree.
alpar@810
    38
alpar@921
    39
namespace lemon {
alpar@810
    40
alpar@810
    41
  /// \addtogroup spantree
alpar@810
    42
  /// @{
alpar@810
    43
alpar@810
    44
  /// Kruskal's algorithm to find a minimum cost tree of a graph.
alpar@810
    45
alpar@810
    46
  /// This function runs Kruskal's algorithm to find a minimum cost tree.
alpar@810
    47
  /// \param G The graph the algorithm runs on. The algorithm considers the
alpar@810
    48
  /// graph to be undirected, the direction of the edges are not used.
alpar@810
    49
  ///
alpar@810
    50
  /// \param in This object is used to describe the edge costs. It must
alpar@810
    51
  /// be an STL compatible 'Forward Container'
alpar@824
    52
  /// with <tt>std::pair<GR::Edge,X></tt> as its <tt>value_type</tt>,
alpar@810
    53
  /// where X is the type of the costs. It must contain every edge in
alpar@810
    54
  /// cost-ascending order.
alpar@810
    55
  ///\par
alpar@810
    56
  /// For the sake of simplicity, there is a helper class KruskalMapInput,
alpar@810
    57
  /// which converts a
alpar@810
    58
  /// simple edge map to an input of this form. Alternatively, you can use
alpar@810
    59
  /// the function \ref kruskalEdgeMap to compute the minimum cost tree if
alpar@810
    60
  /// the edge costs are given by an edge map.
alpar@810
    61
  ///
alpar@810
    62
  /// \retval out This must be a writable \c bool edge map.
alpar@810
    63
  /// After running the algorithm
alpar@810
    64
  /// this will contain the found minimum cost spanning tree: the value of an
alpar@810
    65
  /// edge will be set to \c true if it belongs to the tree, otherwise it will
alpar@810
    66
  /// be set to \c false. The value of each edge will be set exactly once.
alpar@810
    67
  ///
alpar@810
    68
  /// \return The cost of the found tree.
alpar@810
    69
alpar@824
    70
  template <class GR, class IN, class OUT>
alpar@824
    71
  typename IN::value_type::second_type
alpar@824
    72
  kruskal(GR const& G, IN const& in, 
alpar@824
    73
		 OUT& out)
alpar@810
    74
  {
alpar@824
    75
    typedef typename IN::value_type::second_type EdgeCost;
alpar@824
    76
    typedef typename GR::template NodeMap<int> NodeIntMap;
alpar@824
    77
    typedef typename GR::Node Node;
alpar@810
    78
alpar@810
    79
    NodeIntMap comp(G, -1);
alpar@810
    80
    UnionFind<Node,NodeIntMap> uf(comp); 
alpar@810
    81
      
alpar@810
    82
    EdgeCost tot_cost = 0;
alpar@824
    83
    for (typename IN::const_iterator p = in.begin(); 
alpar@810
    84
	 p!=in.end(); ++p ) {
alpar@986
    85
      if ( uf.join(G.target((*p).first),
alpar@986
    86
		   G.source((*p).first)) ) {
alpar@810
    87
	out.set((*p).first, true);
alpar@810
    88
	tot_cost += (*p).second;
alpar@810
    89
      }
alpar@810
    90
      else {
alpar@810
    91
	out.set((*p).first, false);
alpar@810
    92
      }
alpar@810
    93
    }
alpar@810
    94
    return tot_cost;
alpar@810
    95
  }
alpar@810
    96
alpar@810
    97
  /* A work-around for running Kruskal with const-reference bool maps... */
alpar@810
    98
klao@885
    99
  /// Helper class for calling kruskal with "constant" output map.
klao@885
   100
klao@885
   101
  /// Helper class for calling kruskal with output maps constructed
klao@885
   102
  /// on-the-fly.
alpar@810
   103
  ///
klao@885
   104
  /// A typical examle is the following call:
klao@885
   105
  /// <tt>kruskal(G, some_input, makeSequenceOutput(iterator))</tt>.
klao@885
   106
  /// Here, the third argument is a temporary object (which wraps around an
klao@885
   107
  /// iterator with a writable bool map interface), and thus by rules of C++
klao@885
   108
  /// is a \c const object. To enable call like this exist this class and
klao@885
   109
  /// the prototype of the \ref kruskal() function with <tt>const& OUT</tt>
klao@885
   110
  /// third argument.
alpar@824
   111
  template<class Map>
alpar@810
   112
  class NonConstMapWr {
alpar@810
   113
    const Map &m;
alpar@810
   114
  public:
alpar@987
   115
    typedef typename Map::Value Value;
alpar@810
   116
alpar@810
   117
    NonConstMapWr(const Map &_m) : m(_m) {}
alpar@810
   118
alpar@987
   119
    template<class Key>
alpar@987
   120
    void set(Key const& k, Value const &v) const { m.set(k,v); }
alpar@810
   121
  };
alpar@810
   122
alpar@824
   123
  template <class GR, class IN, class OUT>
alpar@810
   124
  inline
klao@885
   125
  typename IN::value_type::second_type
klao@885
   126
  kruskal(GR const& G, IN const& edges, OUT const& out_map)
alpar@810
   127
  {
alpar@824
   128
    NonConstMapWr<OUT> map_wr(out_map);
alpar@810
   129
    return kruskal(G, edges, map_wr);
alpar@810
   130
  }  
alpar@810
   131
alpar@810
   132
  /* ** ** Input-objects ** ** */
alpar@810
   133
alpar@810
   134
  /// Kruskal input source.
alpar@810
   135
alpar@810
   136
  /// Kruskal input source.
alpar@810
   137
  ///
alpar@810
   138
  /// In most cases you possibly want to use the \ref kruskalEdgeMap() instead.
alpar@810
   139
  ///
alpar@810
   140
  /// \sa makeKruskalMapInput()
alpar@810
   141
  ///
alpar@824
   142
  ///\param GR The type of the graph the algorithm runs on.
alpar@810
   143
  ///\param Map An edge map containing the cost of the edges.
alpar@810
   144
  ///\par
alpar@810
   145
  ///The cost type can be any type satisfying
alpar@810
   146
  ///the STL 'LessThan comparable'
alpar@810
   147
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   148
  ///computing the total cost of the tree).
alpar@810
   149
  ///
alpar@824
   150
  template<class GR, class Map>
alpar@810
   151
  class KruskalMapInput
alpar@824
   152
    : public std::vector< std::pair<typename GR::Edge,
alpar@987
   153
				    typename Map::Value> > {
alpar@810
   154
    
alpar@810
   155
  public:
alpar@824
   156
    typedef std::vector< std::pair<typename GR::Edge,
alpar@987
   157
				   typename Map::Value> > Parent;
alpar@810
   158
    typedef typename Parent::value_type value_type;
alpar@810
   159
alpar@810
   160
  private:
alpar@810
   161
    class comparePair {
alpar@810
   162
    public:
alpar@810
   163
      bool operator()(const value_type& a,
alpar@810
   164
		      const value_type& b) {
alpar@810
   165
	return a.second < b.second;
alpar@810
   166
      }
alpar@810
   167
    };
alpar@810
   168
alpar@810
   169
  public:
alpar@810
   170
alpar@810
   171
    void sort() {
alpar@810
   172
      std::sort(this->begin(), this->end(), comparePair());
alpar@810
   173
    }
alpar@810
   174
alpar@824
   175
    KruskalMapInput(GR const& G, Map const& m) {
alpar@824
   176
      typedef typename GR::EdgeIt EdgeIt;
alpar@810
   177
      
klao@885
   178
      for(EdgeIt e(G);e!=INVALID;++e) push_back(value_type(e, m[e]));
alpar@810
   179
      sort();
alpar@810
   180
    }
alpar@810
   181
  };
alpar@810
   182
alpar@810
   183
  /// Creates a KruskalMapInput object for \ref kruskal()
alpar@810
   184
alpar@810
   185
  /// It makes is easier to use 
alpar@810
   186
  /// \ref KruskalMapInput by making it unnecessary 
alpar@810
   187
  /// to explicitly give the type of the parameters.
alpar@810
   188
  ///
alpar@810
   189
  /// In most cases you possibly
alpar@810
   190
  /// want to use the function kruskalEdgeMap() instead.
alpar@810
   191
  ///
alpar@810
   192
  ///\param G The type of the graph the algorithm runs on.
alpar@810
   193
  ///\param m An edge map containing the cost of the edges.
alpar@810
   194
  ///\par
alpar@810
   195
  ///The cost type can be any type satisfying the
alpar@810
   196
  ///STL 'LessThan Comparable'
alpar@810
   197
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   198
  ///computing the total cost of the tree).
alpar@810
   199
  ///
alpar@810
   200
  ///\return An appropriate input source for \ref kruskal().
alpar@810
   201
  ///
alpar@824
   202
  template<class GR, class Map>
alpar@810
   203
  inline
alpar@824
   204
  KruskalMapInput<GR,Map> makeKruskalMapInput(const GR &G,const Map &m)
alpar@810
   205
  {
alpar@824
   206
    return KruskalMapInput<GR,Map>(G,m);
alpar@810
   207
  }
alpar@810
   208
  
alpar@810
   209
  
klao@885
   210
klao@885
   211
  /* ** ** Output-objects: simple writable bool maps ** ** */
alpar@810
   212
  
klao@885
   213
klao@885
   214
alpar@810
   215
  /// A writable bool-map that makes a sequence of "true" keys
alpar@810
   216
alpar@810
   217
  /// A writable bool-map that creates a sequence out of keys that receives
alpar@810
   218
  /// the value "true".
klao@885
   219
  ///
klao@885
   220
  /// \sa makeKruskalSequenceOutput()
klao@885
   221
  ///
klao@885
   222
  /// Very often, when looking for a min cost spanning tree, we want as
klao@885
   223
  /// output a container containing the edges of the found tree. For this
klao@885
   224
  /// purpose exist this class that wraps around an STL iterator with a
klao@885
   225
  /// writable bool map interface. When a key gets value "true" this key
klao@885
   226
  /// is added to sequence pointed by the iterator.
klao@885
   227
  ///
klao@885
   228
  /// A typical usage:
klao@885
   229
  /// \code
klao@885
   230
  /// std::vector<Graph::Edge> v;
klao@885
   231
  /// kruskal(g, input, makeKruskalSequenceOutput(back_inserter(v)));
klao@885
   232
  /// \endcode
klao@885
   233
  /// 
klao@885
   234
  /// For the most common case, when the input is given by a simple edge
klao@885
   235
  /// map and the output is a sequence of the tree edges, a special
klao@885
   236
  /// wrapper function exists: \ref kruskalEdgeMap_IteratorOut().
klao@885
   237
  ///
alpar@987
   238
  /// \warning Not a regular property map, as it doesn't know its Key
klao@885
   239
alpar@824
   240
  template<class Iterator>
klao@885
   241
  class KruskalSequenceOutput {
alpar@810
   242
    mutable Iterator it;
alpar@810
   243
alpar@810
   244
  public:
alpar@987
   245
    typedef bool Value;
alpar@810
   246
klao@885
   247
    KruskalSequenceOutput(Iterator const &_it) : it(_it) {}
alpar@810
   248
alpar@987
   249
    template<typename Key>
alpar@987
   250
    void set(Key const& k, bool v) const { if(v) {*it=k; ++it;} }
alpar@810
   251
  };
alpar@810
   252
alpar@824
   253
  template<class Iterator>
alpar@810
   254
  inline
klao@885
   255
  KruskalSequenceOutput<Iterator>
klao@885
   256
  makeKruskalSequenceOutput(Iterator it) {
klao@885
   257
    return KruskalSequenceOutput<Iterator>(it);
alpar@810
   258
  }
alpar@810
   259
klao@885
   260
klao@885
   261
alpar@810
   262
  /* ** ** Wrapper funtions ** ** */
alpar@810
   263
alpar@810
   264
klao@885
   265
alpar@810
   266
  /// \brief Wrapper function to kruskal().
alpar@810
   267
  /// Input is from an edge map, output is a plain bool map.
alpar@810
   268
  ///
alpar@810
   269
  /// Wrapper function to kruskal().
alpar@810
   270
  /// Input is from an edge map, output is a plain bool map.
alpar@810
   271
  ///
alpar@810
   272
  ///\param G The type of the graph the algorithm runs on.
alpar@810
   273
  ///\param in An edge map containing the cost of the edges.
alpar@810
   274
  ///\par
alpar@810
   275
  ///The cost type can be any type satisfying the
alpar@810
   276
  ///STL 'LessThan Comparable'
alpar@810
   277
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   278
  ///computing the total cost of the tree).
alpar@810
   279
  ///
alpar@810
   280
  /// \retval out This must be a writable \c bool edge map.
alpar@810
   281
  /// After running the algorithm
alpar@810
   282
  /// this will contain the found minimum cost spanning tree: the value of an
alpar@810
   283
  /// edge will be set to \c true if it belongs to the tree, otherwise it will
alpar@810
   284
  /// be set to \c false. The value of each edge will be set exactly once.
alpar@810
   285
  ///
alpar@810
   286
  /// \return The cost of the found tree.
alpar@810
   287
alpar@824
   288
  template <class GR, class IN, class RET>
alpar@810
   289
  inline
alpar@987
   290
  typename IN::Value
alpar@824
   291
  kruskalEdgeMap(GR const& G,
alpar@824
   292
		 IN const& in,
alpar@824
   293
		 RET &out) {
alpar@810
   294
    return kruskal(G,
alpar@824
   295
		   KruskalMapInput<GR,IN>(G,in),
alpar@810
   296
		   out);
alpar@810
   297
  }
alpar@810
   298
alpar@810
   299
  /// \brief Wrapper function to kruskal().
alpar@810
   300
  /// Input is from an edge map, output is an STL Sequence.
alpar@810
   301
  ///
alpar@810
   302
  /// Wrapper function to kruskal().
alpar@810
   303
  /// Input is from an edge map, output is an STL Sequence.
alpar@810
   304
  ///
alpar@810
   305
  ///\param G The type of the graph the algorithm runs on.
alpar@810
   306
  ///\param in An edge map containing the cost of the edges.
alpar@810
   307
  ///\par
alpar@810
   308
  ///The cost type can be any type satisfying the
alpar@810
   309
  ///STL 'LessThan Comparable'
alpar@810
   310
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   311
  ///computing the total cost of the tree).
alpar@810
   312
  ///
alpar@810
   313
  /// \retval out This must be an iteraror of an STL Container with
alpar@824
   314
  /// <tt>GR::Edge</tt> as its <tt>value_type</tt>.
alpar@810
   315
  /// The algorithm copies the elements of the found tree into this sequence.
alpar@810
   316
  /// For example, if we know that the spanning tree of the graph \c G has
alpar@810
   317
  /// say 53 edges then
alpar@824
   318
  /// we can put its edges into a STL vector \c tree with a code like this.
alpar@810
   319
  /// \code
alpar@810
   320
  /// std::vector<Edge> tree(53);
alpar@810
   321
  /// kruskalEdgeMap_IteratorOut(G,cost,tree.begin());
alpar@810
   322
  /// \endcode
alpar@810
   323
  /// Or if we don't know in advance the size of the tree, we can write this.
alpar@810
   324
  /// \code
alpar@810
   325
  /// std::vector<Edge> tree;
alpar@810
   326
  /// kruskalEdgeMap_IteratorOut(G,cost,std::back_inserter(tree));
alpar@810
   327
  /// \endcode
alpar@810
   328
  ///
alpar@810
   329
  /// \return The cost of the found tree.
alpar@810
   330
  ///
alpar@810
   331
  /// \bug its name does not follow the coding style.
klao@885
   332
alpar@824
   333
  template <class GR, class IN, class RET>
alpar@810
   334
  inline
alpar@987
   335
  typename IN::Value
alpar@824
   336
  kruskalEdgeMap_IteratorOut(const GR& G,
alpar@824
   337
			     const IN& in,
alpar@824
   338
			     RET out)
alpar@810
   339
  {
klao@885
   340
    KruskalSequenceOutput<RET> _out(out);
klao@885
   341
    return kruskal(G, KruskalMapInput<GR,IN>(G, in), _out);
alpar@810
   342
  }
alpar@810
   343
alpar@810
   344
  /// @}
alpar@810
   345
alpar@921
   346
} //namespace lemon
alpar@810
   347
alpar@921
   348
#endif //LEMON_KRUSKAL_H