lemon/kruskal.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1631 e15162d8eca1
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
alpar@906
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * 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@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, 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@1449
    22
#include<lemon/utility.h>
alpar@810
    23
alpar@810
    24
/**
alpar@810
    25
@defgroup spantree Minimum Cost Spanning Tree Algorithms
alpar@810
    26
@ingroup galgs
alpar@810
    27
\brief This group containes the algorithms for finding a minimum cost spanning
alpar@810
    28
tree in a graph
alpar@810
    29
alpar@810
    30
This group containes the algorithms for finding a minimum cost spanning
alpar@810
    31
tree in a graph
alpar@810
    32
*/
alpar@810
    33
alpar@810
    34
///\ingroup spantree
alpar@810
    35
///\file
alpar@810
    36
///\brief Kruskal's algorithm to compute a minimum cost tree
alpar@810
    37
///
alpar@810
    38
///Kruskal's algorithm to compute a minimum cost tree.
alpar@1557
    39
///
alpar@1557
    40
///\todo The file still needs some clean-up.
alpar@810
    41
alpar@921
    42
namespace lemon {
alpar@810
    43
alpar@810
    44
  /// \addtogroup spantree
alpar@810
    45
  /// @{
alpar@810
    46
alpar@810
    47
  /// Kruskal's algorithm to find a minimum cost tree of a graph.
alpar@810
    48
alpar@810
    49
  /// This function runs Kruskal's algorithm to find a minimum cost tree.
alpar@1557
    50
  /// Due to hard C++ hacking, it accepts various input and output types.
alpar@1557
    51
  ///
alpar@1555
    52
  /// \param g The graph the algorithm runs on.
alpar@1555
    53
  /// It can be either \ref concept::StaticGraph "directed" or 
alpar@1631
    54
  /// \ref concept::UndirGraph "undirected".
alpar@1555
    55
  /// If the graph is directed, the algorithm consider it to be 
alpar@1555
    56
  /// undirected by disregarding the direction of the edges.
alpar@810
    57
  ///
alpar@1557
    58
  /// \param in This object is used to describe the edge costs. It can be one
alpar@1557
    59
  /// of the following choices.
alpar@1557
    60
  /// - An STL compatible 'Forward Container'
alpar@824
    61
  /// with <tt>std::pair<GR::Edge,X></tt> as its <tt>value_type</tt>,
alpar@1557
    62
  /// where \c X is the type of the costs. The pairs indicates the edges along
alpar@1557
    63
  /// with the assigned cost. <em>They must be in a
alpar@1557
    64
  /// cost-ascending order.</em>
alpar@1557
    65
  /// - Any readable Edge map. The values of the map indicate the edge costs.
alpar@810
    66
  ///
alpar@1557
    67
  /// \retval out Here we also have a choise.
alpar@1557
    68
  /// - Is can be a writable \c bool edge map. 
alpar@810
    69
  /// After running the algorithm
alpar@810
    70
  /// this will contain the found minimum cost spanning tree: the value of an
alpar@810
    71
  /// edge will be set to \c true if it belongs to the tree, otherwise it will
alpar@810
    72
  /// be set to \c false. The value of each edge will be set exactly once.
alpar@1557
    73
  /// - It can also be an iteraror of an STL Container with
alpar@1557
    74
  /// <tt>GR::Edge</tt> as its <tt>value_type</tt>.
alpar@1557
    75
  /// The algorithm copies the elements of the found tree into this sequence.
alpar@1557
    76
  /// For example, if we know that the spanning tree of the graph \c g has
alpar@1603
    77
  /// say 53 edges, then
alpar@1557
    78
  /// we can put its edges into a STL vector \c tree with a code like this.
alpar@1557
    79
  /// \code
alpar@1557
    80
  /// std::vector<Edge> tree(53);
alpar@1557
    81
  /// kruskal(g,cost,tree.begin());
alpar@1557
    82
  /// \endcode
alpar@1557
    83
  /// Or if we don't know in advance the size of the tree, we can write this.
alpar@1557
    84
  /// \code
alpar@1557
    85
  /// std::vector<Edge> tree;
alpar@1557
    86
  /// kruskal(g,cost,std::back_inserter(tree));
alpar@1557
    87
  /// \endcode
alpar@810
    88
  ///
alpar@810
    89
  /// \return The cost of the found tree.
alpar@1449
    90
  ///
alpar@1631
    91
  /// \warning If kruskal is run on an
alpar@1631
    92
  /// \ref lemon::concept::UndirGraph "undirected graph", be sure that the
alpar@1603
    93
  /// map storing the tree is also undirected
alpar@1603
    94
  /// (e.g. UndirListGraph::UndirEdgeMap<bool>, otherwise the values of the
alpar@1603
    95
  /// half of the edges will not be set.
alpar@1603
    96
  ///
alpar@1449
    97
  /// \todo Discuss the case of undirected graphs: In this case the algorithm
alpar@1449
    98
  /// also require <tt>Edge</tt>s instead of <tt>UndirEdge</tt>s, as some
alpar@1449
    99
  /// people would expect. So, one should be careful not to add both of the
alpar@1449
   100
  /// <tt>Edge</tt>s belonging to a certain <tt>UndirEdge</tt>.
alpar@1570
   101
  /// (\ref kruskal() and \ref KruskalMapInput are kind enough to do so.)
alpar@810
   102
alpar@1557
   103
#ifdef DOXYGEN
alpar@824
   104
  template <class GR, class IN, class OUT>
alpar@824
   105
  typename IN::value_type::second_type
alpar@1547
   106
  kruskal(GR const& g, IN const& in, 
alpar@1557
   107
	  OUT& out)
alpar@1557
   108
#else
alpar@1557
   109
  template <class GR, class IN, class OUT>
alpar@1557
   110
  typename IN::value_type::second_type
alpar@1557
   111
  kruskal(GR const& g, IN const& in, 
alpar@1557
   112
	  OUT& out,
alpar@1557
   113
// 	  typename IN::value_type::first_type = typename GR::Edge()
alpar@1557
   114
// 	  ,typename OUT::Key = OUT::Key()
alpar@1557
   115
// 	  //,typename OUT::Key = typename GR::Edge()
alpar@1557
   116
	  const typename IN::value_type::first_type * = 
alpar@1557
   117
	  (const typename IN::value_type::first_type *)(0),
alpar@1557
   118
	  const typename OUT::Key * = (const typename OUT::Key *)(0)
alpar@1557
   119
	  )
alpar@1557
   120
#endif
alpar@810
   121
  {
alpar@824
   122
    typedef typename IN::value_type::second_type EdgeCost;
alpar@824
   123
    typedef typename GR::template NodeMap<int> NodeIntMap;
alpar@824
   124
    typedef typename GR::Node Node;
alpar@810
   125
alpar@1547
   126
    NodeIntMap comp(g, -1);
alpar@810
   127
    UnionFind<Node,NodeIntMap> uf(comp); 
alpar@810
   128
      
alpar@810
   129
    EdgeCost tot_cost = 0;
alpar@824
   130
    for (typename IN::const_iterator p = in.begin(); 
alpar@810
   131
	 p!=in.end(); ++p ) {
alpar@1547
   132
      if ( uf.join(g.target((*p).first),
alpar@1547
   133
		   g.source((*p).first)) ) {
alpar@810
   134
	out.set((*p).first, true);
alpar@810
   135
	tot_cost += (*p).second;
alpar@810
   136
      }
alpar@810
   137
      else {
alpar@810
   138
	out.set((*p).first, false);
alpar@810
   139
      }
alpar@810
   140
    }
alpar@810
   141
    return tot_cost;
alpar@810
   142
  }
alpar@810
   143
alpar@1557
   144
 
alpar@1557
   145
  /// @}
alpar@1557
   146
alpar@1557
   147
  
alpar@810
   148
  /* A work-around for running Kruskal with const-reference bool maps... */
alpar@810
   149
klao@885
   150
  /// Helper class for calling kruskal with "constant" output map.
klao@885
   151
klao@885
   152
  /// Helper class for calling kruskal with output maps constructed
klao@885
   153
  /// on-the-fly.
alpar@810
   154
  ///
klao@885
   155
  /// A typical examle is the following call:
alpar@1547
   156
  /// <tt>kruskal(g, some_input, makeSequenceOutput(iterator))</tt>.
klao@885
   157
  /// Here, the third argument is a temporary object (which wraps around an
klao@885
   158
  /// iterator with a writable bool map interface), and thus by rules of C++
klao@885
   159
  /// is a \c const object. To enable call like this exist this class and
klao@885
   160
  /// the prototype of the \ref kruskal() function with <tt>const& OUT</tt>
klao@885
   161
  /// third argument.
alpar@824
   162
  template<class Map>
alpar@810
   163
  class NonConstMapWr {
alpar@810
   164
    const Map &m;
alpar@810
   165
  public:
alpar@1557
   166
    typedef typename Map::Key Key;
alpar@987
   167
    typedef typename Map::Value Value;
alpar@810
   168
alpar@810
   169
    NonConstMapWr(const Map &_m) : m(_m) {}
alpar@810
   170
alpar@987
   171
    template<class Key>
alpar@987
   172
    void set(Key const& k, Value const &v) const { m.set(k,v); }
alpar@810
   173
  };
alpar@810
   174
alpar@824
   175
  template <class GR, class IN, class OUT>
alpar@810
   176
  inline
klao@885
   177
  typename IN::value_type::second_type
alpar@1557
   178
  kruskal(GR const& g, IN const& edges, OUT const& out_map,
alpar@1557
   179
// 	  typename IN::value_type::first_type = typename GR::Edge(),
alpar@1557
   180
// 	  typename OUT::Key = GR::Edge()
alpar@1557
   181
	  const typename IN::value_type::first_type * = 
alpar@1557
   182
	  (const typename IN::value_type::first_type *)(0),
alpar@1557
   183
	  const typename OUT::Key * = (const typename OUT::Key *)(0)
alpar@1557
   184
	  )
alpar@810
   185
  {
alpar@824
   186
    NonConstMapWr<OUT> map_wr(out_map);
alpar@1547
   187
    return kruskal(g, edges, map_wr);
alpar@810
   188
  }  
alpar@810
   189
alpar@810
   190
  /* ** ** Input-objects ** ** */
alpar@810
   191
zsuzska@1274
   192
  /// Kruskal's input source.
alpar@1557
   193
 
zsuzska@1274
   194
  /// Kruskal's input source.
alpar@810
   195
  ///
alpar@1570
   196
  /// In most cases you possibly want to use the \ref kruskal() instead.
alpar@810
   197
  ///
alpar@810
   198
  /// \sa makeKruskalMapInput()
alpar@810
   199
  ///
alpar@824
   200
  ///\param GR The type of the graph the algorithm runs on.
alpar@810
   201
  ///\param Map An edge map containing the cost of the edges.
alpar@810
   202
  ///\par
alpar@810
   203
  ///The cost type can be any type satisfying
alpar@810
   204
  ///the STL 'LessThan comparable'
alpar@810
   205
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   206
  ///computing the total cost of the tree).
alpar@810
   207
  ///
alpar@824
   208
  template<class GR, class Map>
alpar@810
   209
  class KruskalMapInput
alpar@824
   210
    : public std::vector< std::pair<typename GR::Edge,
alpar@987
   211
				    typename Map::Value> > {
alpar@810
   212
    
alpar@810
   213
  public:
alpar@824
   214
    typedef std::vector< std::pair<typename GR::Edge,
alpar@987
   215
				   typename Map::Value> > Parent;
alpar@810
   216
    typedef typename Parent::value_type value_type;
alpar@810
   217
alpar@810
   218
  private:
alpar@810
   219
    class comparePair {
alpar@810
   220
    public:
alpar@810
   221
      bool operator()(const value_type& a,
alpar@810
   222
		      const value_type& b) {
alpar@810
   223
	return a.second < b.second;
alpar@810
   224
      }
alpar@810
   225
    };
alpar@810
   226
alpar@1449
   227
    template<class _GR>
alpar@1449
   228
    typename enable_if<typename _GR::UndirTag,void>::type
alpar@1547
   229
    fillWithEdges(const _GR& g, const Map& m,dummy<0> = 0) 
alpar@1449
   230
    {
alpar@1547
   231
      for(typename GR::UndirEdgeIt e(g);e!=INVALID;++e) 
deba@1679
   232
	push_back(value_type(g.direct(e, true), m[e]));
alpar@1449
   233
    }
alpar@1449
   234
alpar@1449
   235
    template<class _GR>
alpar@1449
   236
    typename disable_if<typename _GR::UndirTag,void>::type
alpar@1547
   237
    fillWithEdges(const _GR& g, const Map& m,dummy<1> = 1) 
alpar@1449
   238
    {
alpar@1547
   239
      for(typename GR::EdgeIt e(g);e!=INVALID;++e) 
alpar@1449
   240
	push_back(value_type(e, m[e]));
alpar@1449
   241
    }
alpar@1449
   242
    
alpar@1449
   243
    
alpar@810
   244
  public:
alpar@810
   245
alpar@810
   246
    void sort() {
alpar@810
   247
      std::sort(this->begin(), this->end(), comparePair());
alpar@810
   248
    }
alpar@810
   249
alpar@1547
   250
    KruskalMapInput(GR const& g, Map const& m) {
alpar@1547
   251
      fillWithEdges(g,m); 
alpar@810
   252
      sort();
alpar@810
   253
    }
alpar@810
   254
  };
alpar@810
   255
alpar@810
   256
  /// Creates a KruskalMapInput object for \ref kruskal()
alpar@810
   257
zsuzska@1274
   258
  /// It makes easier to use 
alpar@810
   259
  /// \ref KruskalMapInput by making it unnecessary 
alpar@810
   260
  /// to explicitly give the type of the parameters.
alpar@810
   261
  ///
alpar@810
   262
  /// In most cases you possibly
alpar@1570
   263
  /// want to use \ref kruskal() instead.
alpar@810
   264
  ///
alpar@1547
   265
  ///\param g The type of the graph the algorithm runs on.
alpar@810
   266
  ///\param m An edge map containing the cost of the edges.
alpar@810
   267
  ///\par
alpar@810
   268
  ///The cost type can be any type satisfying the
alpar@810
   269
  ///STL 'LessThan Comparable'
alpar@810
   270
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   271
  ///computing the total cost of the tree).
alpar@810
   272
  ///
alpar@810
   273
  ///\return An appropriate input source for \ref kruskal().
alpar@810
   274
  ///
alpar@824
   275
  template<class GR, class Map>
alpar@810
   276
  inline
alpar@1547
   277
  KruskalMapInput<GR,Map> makeKruskalMapInput(const GR &g,const Map &m)
alpar@810
   278
  {
alpar@1547
   279
    return KruskalMapInput<GR,Map>(g,m);
alpar@810
   280
  }
alpar@810
   281
  
alpar@810
   282
  
klao@885
   283
klao@885
   284
  /* ** ** Output-objects: simple writable bool maps ** ** */
alpar@810
   285
  
klao@885
   286
klao@885
   287
alpar@810
   288
  /// A writable bool-map that makes a sequence of "true" keys
alpar@810
   289
alpar@810
   290
  /// A writable bool-map that creates a sequence out of keys that receives
alpar@810
   291
  /// the value "true".
klao@885
   292
  ///
klao@885
   293
  /// \sa makeKruskalSequenceOutput()
klao@885
   294
  ///
klao@885
   295
  /// Very often, when looking for a min cost spanning tree, we want as
klao@885
   296
  /// output a container containing the edges of the found tree. For this
klao@885
   297
  /// purpose exist this class that wraps around an STL iterator with a
klao@885
   298
  /// writable bool map interface. When a key gets value "true" this key
klao@885
   299
  /// is added to sequence pointed by the iterator.
klao@885
   300
  ///
klao@885
   301
  /// A typical usage:
klao@885
   302
  /// \code
klao@885
   303
  /// std::vector<Graph::Edge> v;
klao@885
   304
  /// kruskal(g, input, makeKruskalSequenceOutput(back_inserter(v)));
klao@885
   305
  /// \endcode
klao@885
   306
  /// 
klao@885
   307
  /// For the most common case, when the input is given by a simple edge
klao@885
   308
  /// map and the output is a sequence of the tree edges, a special
klao@885
   309
  /// wrapper function exists: \ref kruskalEdgeMap_IteratorOut().
klao@885
   310
  ///
alpar@987
   311
  /// \warning Not a regular property map, as it doesn't know its Key
klao@885
   312
alpar@824
   313
  template<class Iterator>
klao@885
   314
  class KruskalSequenceOutput {
alpar@810
   315
    mutable Iterator it;
alpar@810
   316
alpar@810
   317
  public:
alpar@1557
   318
    typedef typename Iterator::value_type Key;
alpar@987
   319
    typedef bool Value;
alpar@810
   320
klao@885
   321
    KruskalSequenceOutput(Iterator const &_it) : it(_it) {}
alpar@810
   322
alpar@987
   323
    template<typename Key>
alpar@987
   324
    void set(Key const& k, bool v) const { if(v) {*it=k; ++it;} }
alpar@810
   325
  };
alpar@810
   326
alpar@824
   327
  template<class Iterator>
alpar@810
   328
  inline
klao@885
   329
  KruskalSequenceOutput<Iterator>
klao@885
   330
  makeKruskalSequenceOutput(Iterator it) {
klao@885
   331
    return KruskalSequenceOutput<Iterator>(it);
alpar@810
   332
  }
alpar@810
   333
klao@885
   334
klao@885
   335
alpar@810
   336
  /* ** ** Wrapper funtions ** ** */
alpar@810
   337
alpar@1557
   338
//   \brief Wrapper function to kruskal().
alpar@1557
   339
//   Input is from an edge map, output is a plain bool map.
alpar@1557
   340
//  
alpar@1557
   341
//   Wrapper function to kruskal().
alpar@1557
   342
//   Input is from an edge map, output is a plain bool map.
alpar@1557
   343
//  
alpar@1557
   344
//   \param g The type of the graph the algorithm runs on.
alpar@1557
   345
//   \param in An edge map containing the cost of the edges.
alpar@1557
   346
//   \par
alpar@1557
   347
//   The cost type can be any type satisfying the
alpar@1557
   348
//   STL 'LessThan Comparable'
alpar@1557
   349
//   concept if it also has an operator+() implemented. (It is necessary for
alpar@1557
   350
//   computing the total cost of the tree).
alpar@1557
   351
//  
alpar@1557
   352
//   \retval out This must be a writable \c bool edge map.
alpar@1557
   353
//   After running the algorithm
alpar@1557
   354
//   this will contain the found minimum cost spanning tree: the value of an
alpar@1557
   355
//   edge will be set to \c true if it belongs to the tree, otherwise it will
alpar@1557
   356
//   be set to \c false. The value of each edge will be set exactly once.
alpar@1557
   357
//  
alpar@1557
   358
//   \return The cost of the found tree.
alpar@810
   359
alpar@824
   360
  template <class GR, class IN, class RET>
alpar@810
   361
  inline
alpar@987
   362
  typename IN::Value
alpar@1557
   363
  kruskal(GR const& g,
alpar@1557
   364
	  IN const& in,
alpar@1557
   365
	  RET &out,
alpar@1557
   366
	  //	  typename IN::Key = typename GR::Edge(),
alpar@1557
   367
	  //typename IN::Key = typename IN::Key (),
alpar@1557
   368
	  //	  typename RET::Key = typename GR::Edge()
alpar@1557
   369
	  const typename IN::Key *  = (const typename IN::Key *)(0),
alpar@1557
   370
	  const typename RET::Key * = (const typename RET::Key *)(0)
alpar@1557
   371
	  )
alpar@1557
   372
  {
alpar@1547
   373
    return kruskal(g,
alpar@1547
   374
		   KruskalMapInput<GR,IN>(g,in),
alpar@810
   375
		   out);
alpar@810
   376
  }
alpar@810
   377
alpar@1557
   378
//   \brief Wrapper function to kruskal().
alpar@1557
   379
//   Input is from an edge map, output is an STL Sequence.
alpar@1557
   380
//  
alpar@1557
   381
//   Wrapper function to kruskal().
alpar@1557
   382
//   Input is from an edge map, output is an STL Sequence.
alpar@1557
   383
//  
alpar@1557
   384
//   \param g The type of the graph the algorithm runs on.
alpar@1557
   385
//   \param in An edge map containing the cost of the edges.
alpar@1557
   386
//   \par
alpar@1557
   387
//   The cost type can be any type satisfying the
alpar@1557
   388
//   STL 'LessThan Comparable'
alpar@1557
   389
//   concept if it also has an operator+() implemented. (It is necessary for
alpar@1557
   390
//   computing the total cost of the tree).
alpar@1557
   391
//  
alpar@1557
   392
//   \retval out This must be an iteraror of an STL Container with
alpar@1557
   393
//   <tt>GR::Edge</tt> as its <tt>value_type</tt>.
alpar@1557
   394
//   The algorithm copies the elements of the found tree into this sequence.
alpar@1557
   395
//   For example, if we know that the spanning tree of the graph \c g has
alpar@1603
   396
//   say 53 edges, then
alpar@1557
   397
//   we can put its edges into a STL vector \c tree with a code like this.
alpar@1557
   398
//   \code
alpar@1557
   399
//   std::vector<Edge> tree(53);
alpar@1570
   400
//   kruskal(g,cost,tree.begin());
alpar@1557
   401
//   \endcode
alpar@1557
   402
//   Or if we don't know in advance the size of the tree, we can write this.
alpar@1557
   403
//   \code
alpar@1557
   404
//   std::vector<Edge> tree;
alpar@1570
   405
//   kruskal(g,cost,std::back_inserter(tree));
alpar@1557
   406
//   \endcode
alpar@1557
   407
//  
alpar@1557
   408
//   \return The cost of the found tree.
alpar@1557
   409
//  
alpar@1557
   410
//   \bug its name does not follow the coding style.
klao@885
   411
alpar@824
   412
  template <class GR, class IN, class RET>
alpar@810
   413
  inline
alpar@987
   414
  typename IN::Value
alpar@1557
   415
  kruskal(const GR& g,
alpar@1557
   416
	  const IN& in,
alpar@1557
   417
	  RET out,
alpar@1557
   418
	  //,typename RET::value_type = typename GR::Edge()
alpar@1557
   419
	  //,typename RET::value_type = typename RET::value_type()
alpar@1557
   420
	  const typename RET::value_type * = 
alpar@1557
   421
	  (const typename RET::value_type *)(0)
alpar@1557
   422
	  )
alpar@810
   423
  {
klao@885
   424
    KruskalSequenceOutput<RET> _out(out);
alpar@1547
   425
    return kruskal(g, KruskalMapInput<GR,IN>(g, in), _out);
alpar@810
   426
  }
alpar@1557
   427
 
alpar@810
   428
  /// @}
alpar@810
   429
alpar@921
   430
} //namespace lemon
alpar@810
   431
alpar@921
   432
#endif //LEMON_KRUSKAL_H