lemon/kruskal.h
author kpeter
Wed, 05 Dec 2007 01:43:02 +0000
changeset 2533 aea952a1af99
parent 2428 c06e86364234
child 2553 bfced05fa852
permissions -rw-r--r--
Bug fixes.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@2391
     5
 * Copyright (C) 2003-2007
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@906
    18
alpar@921
    19
#ifndef LEMON_KRUSKAL_H
alpar@921
    20
#define LEMON_KRUSKAL_H
alpar@810
    21
alpar@810
    22
#include <algorithm>
klao@1942
    23
#include <vector>
alpar@921
    24
#include <lemon/unionfind.h>
deba@2424
    25
#include <lemon/graph_utils.h>
deba@2424
    26
#include <lemon/maps.h>
deba@2424
    27
deba@2424
    28
#include <lemon/radix_sort.h>
deba@2424
    29
deba@1993
    30
#include <lemon/bits/utility.h>
deba@1993
    31
#include <lemon/bits/traits.h>
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@1557
    38
///
alpar@810
    39
alpar@921
    40
namespace lemon {
alpar@810
    41
deba@2424
    42
  namespace _kruskal_bits {
alpar@810
    43
deba@2424
    44
    template <typename Map, typename Comp>
deba@2424
    45
    struct MappedComp {
alpar@810
    46
deba@2424
    47
      typedef typename Map::Key Key;
deba@2424
    48
deba@2424
    49
      const Map& map;
deba@2424
    50
      Comp comp;
deba@2424
    51
deba@2424
    52
      MappedComp(const Map& _map) 
deba@2424
    53
        : map(_map), comp() {}
deba@2424
    54
deba@2424
    55
      bool operator()(const Key& left, const Key& right) {
deba@2424
    56
        return comp(map[left], map[right]);
deba@2424
    57
      }
deba@2424
    58
deba@2424
    59
    };
deba@2424
    60
  
deba@2424
    61
  }
deba@2424
    62
deba@2424
    63
  /// \brief Default traits class of Kruskal class.
deba@2424
    64
  ///
deba@2424
    65
  /// Default traits class of Kruskal class.
deba@2424
    66
  /// \param _UGraph Undirected graph type.
deba@2424
    67
  /// \param _CostMap Type of cost map.
deba@2424
    68
  template <typename _UGraph, typename _CostMap>
deba@2424
    69
  struct KruskalDefaultTraits{
deba@2424
    70
deba@2424
    71
    /// \brief The graph type the algorithm runs on. 
deba@2424
    72
    typedef _UGraph UGraph;
deba@2424
    73
deba@2424
    74
    /// \brief The type of the map that stores the edge costs.
deba@2424
    75
    ///
deba@2424
    76
    /// The type of the map that stores the edge costs.
deba@2424
    77
    /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
deba@2424
    78
    typedef _CostMap CostMap;
deba@2424
    79
deba@2424
    80
    /// \brief The type of the cost of the edges.
deba@2424
    81
    typedef typename _CostMap::Value Value;
deba@2424
    82
deba@2424
    83
    /// \brief The type of the map that stores whether an edge is in the
deba@2424
    84
    /// spanning tree or not.
deba@2424
    85
    ///
deba@2424
    86
    /// The type of the map that stores whether an edge is in the
deba@2424
    87
    /// spanning tree or not.
deba@2424
    88
    typedef typename _UGraph::template UEdgeMap<bool> TreeMap;
deba@2424
    89
deba@2424
    90
    /// \brief Instantiates a TreeMap.
deba@2424
    91
    ///
deba@2424
    92
    /// This function instantiates a \ref TreeMap.
deba@2424
    93
    ///
deba@2424
    94
    /// The first parameter is the graph, to which
deba@2424
    95
    /// we would like to define the \ref TreeMap
deba@2424
    96
    static TreeMap *createTreeMap(const _UGraph& graph){
deba@2424
    97
      return new TreeMap(graph);
deba@2424
    98
    }
deba@2424
    99
deba@2424
   100
    template <typename Iterator>
deba@2424
   101
    static void sort(Iterator begin, Iterator end, const CostMap& cost) {
deba@2424
   102
      _kruskal_bits::MappedComp<CostMap, std::less<Value> > comp(cost);
deba@2424
   103
      std::sort(begin, end, comp);
deba@2424
   104
    }
deba@2424
   105
deba@2424
   106
  };
deba@2424
   107
deba@2428
   108
  ///\ingroup spantree
deba@2428
   109
  ///
deba@2424
   110
  /// \brief Kruskal's algorithm to find a minimum cost tree of a graph.
deba@2424
   111
  ///
deba@2424
   112
  /// This class implements Kruskal's algorithm to find a minimum cost
deba@2424
   113
  /// spanning tree. The 
deba@2424
   114
  ///
deba@2424
   115
  /// \param _UGraph Undirected graph type.
deba@2424
   116
  /// \param _CostMap Type of cost map.
deba@2424
   117
  template <typename _UGraph, typename _CostMap,
deba@2424
   118
            typename _Traits = KruskalDefaultTraits<_UGraph, _CostMap> >
deba@2424
   119
  class Kruskal {
deba@2424
   120
  public:
deba@2424
   121
deba@2424
   122
    typedef _Traits Traits;
deba@2424
   123
deba@2424
   124
    typedef typename _Traits::UGraph UGraph;
deba@2424
   125
    typedef typename _Traits::CostMap CostMap;
deba@2424
   126
deba@2424
   127
    typedef typename _Traits::TreeMap TreeMap;
deba@2424
   128
deba@2424
   129
    typedef typename _Traits::Value Value;
deba@2424
   130
deba@2424
   131
    template <typename Comp>
deba@2424
   132
    struct DefSortCompareTraits : public Traits {
deba@2424
   133
      template <typename Iterator>
deba@2424
   134
      static void sort(Iterator begin, Iterator end, const CostMap& cost) {
deba@2424
   135
        _kruskal_bits::MappedComp<CostMap, Comp> comp(cost, Comp());
deba@2424
   136
        std::sort(begin, end, comp);
deba@2424
   137
      }
deba@2424
   138
    };
deba@2424
   139
deba@2424
   140
    /// \brief \ref named-templ-param "Named parameter" for setting the
deba@2424
   141
    /// comparator object of the standard sort
deba@2424
   142
    ///
deba@2424
   143
    /// \ref named-templ-param "Named parameter" for setting the
deba@2424
   144
    /// comparator object of the standard sort
deba@2424
   145
    template <typename Comp>
deba@2424
   146
    struct DefSortCompare
deba@2424
   147
      : public Kruskal<UGraph, CostMap, DefSortCompareTraits<Comp> > {
deba@2424
   148
      typedef Kruskal<UGraph, CostMap, DefSortCompareTraits<Comp> > Create;
deba@2424
   149
    };    
deba@2424
   150
deba@2424
   151
    struct DefRadixSortTraits : public Traits {
deba@2424
   152
      template <typename Iterator>
deba@2424
   153
      static void sort(Iterator begin, Iterator end, const CostMap& cost) {
deba@2424
   154
        radixSort(begin, end, cost);
deba@2424
   155
      }
deba@2424
   156
    };
deba@2424
   157
deba@2424
   158
    /// \brief \ref named-templ-param "Named parameter" for setting the
deba@2424
   159
    /// sort function to radix sort
deba@2424
   160
    ///
deba@2424
   161
    /// \brief \ref named-templ-param "Named parameter" for setting the
deba@2424
   162
    /// sort function to radix sort. The value type of the cost map should
deba@2424
   163
    /// be integral, of course. 
deba@2424
   164
    struct DefRadixSort
deba@2424
   165
      : public Kruskal<UGraph, CostMap, DefRadixSortTraits> {
deba@2424
   166
      typedef Kruskal<UGraph, CostMap, DefRadixSortTraits> Create;
deba@2424
   167
    };    
deba@2424
   168
deba@2424
   169
    template <class TM>
deba@2424
   170
    struct DefTreeMapTraits : public Traits {
deba@2424
   171
      typedef TM TreeMap;
deba@2424
   172
      static TreeMap *createTreeMap(const UGraph &) {
deba@2424
   173
        throw UninitializedParameter();
deba@2424
   174
      }
deba@2424
   175
    };
deba@2424
   176
deba@2424
   177
    /// \brief \ref named-templ-param "Named parameter" for setting
deba@2424
   178
    /// TreeMap
deba@2424
   179
    ///
deba@2424
   180
    /// \ref named-templ-param "Named parameter" for setting TreeMap
deba@2424
   181
    ///
deba@2424
   182
    template <class TM>
deba@2424
   183
    struct DefTreeMap
deba@2424
   184
      : public Kruskal< UGraph, CostMap, DefTreeMapTraits<TM> > {
deba@2424
   185
      typedef Kruskal< UGraph, CostMap, DefTreeMapTraits<TM> > Create;
deba@2424
   186
    };    
deba@2424
   187
    
deba@2424
   188
deba@2424
   189
  private:
deba@2424
   190
deba@2424
   191
    typedef typename UGraph::Node Node;
deba@2424
   192
    typedef typename UGraph::NodeIt NodeIt;
deba@2424
   193
deba@2424
   194
    typedef typename UGraph::UEdge UEdge;
deba@2424
   195
    typedef typename UGraph::UEdgeIt UEdgeIt;
deba@2424
   196
deba@2424
   197
    const UGraph& graph;
deba@2424
   198
    const CostMap& cost;
deba@2424
   199
    
deba@2424
   200
    std::vector<UEdge> edges;
deba@2424
   201
    
deba@2424
   202
    typedef typename UGraph::template NodeMap<int> UfIndex;
deba@2424
   203
    typedef UnionFind<UfIndex> Uf;
deba@2424
   204
    UfIndex *ufi;
deba@2424
   205
    Uf *uf;
deba@2424
   206
deba@2424
   207
    int index;
deba@2424
   208
deba@2424
   209
    void initStructures() {
deba@2424
   210
      if (!_tree) {
deba@2424
   211
        _tree = Traits::createTreeMap(graph);
deba@2424
   212
        local_tree = true;
deba@2424
   213
      }
deba@2424
   214
      if (!uf) {
deba@2424
   215
        ufi = new typename UGraph::template NodeMap<int>(graph);
deba@2424
   216
        uf = new UnionFind<typename UGraph::template NodeMap<int> >(*ufi);
deba@2424
   217
      }
deba@2424
   218
    }
deba@2424
   219
    
deba@2424
   220
    void initUnionFind() {
deba@2424
   221
      uf->clear();
deba@2424
   222
      for (NodeIt it(graph); it != INVALID; ++it) {
deba@2424
   223
        uf->insert(it);
deba@2424
   224
      }
deba@2424
   225
    }
deba@2424
   226
deba@2424
   227
    bool local_tree;
deba@2424
   228
    TreeMap* _tree;
deba@2424
   229
deba@2424
   230
  public:
deba@2424
   231
deba@2424
   232
    /// \brief Constructor
deba@2424
   233
    ///
deba@2424
   234
    /// Constructor of the algorithm.
deba@2424
   235
    Kruskal(const UGraph& _graph, const CostMap& _cost) 
deba@2424
   236
      : graph(_graph), cost(_cost),
deba@2424
   237
        ufi(0), uf(0), local_tree(false), _tree(0) {}
deba@2424
   238
deba@2424
   239
    /// \brief Destructor
deba@2424
   240
    ///
deba@2424
   241
    /// Destructor
deba@2424
   242
    ~Kruskal() {
deba@2424
   243
      if (local_tree) {
deba@2424
   244
        delete _tree;
deba@2424
   245
      }
deba@2424
   246
      if (uf) {
deba@2424
   247
        delete uf;
deba@2424
   248
        delete ufi;
deba@2424
   249
      }
deba@2424
   250
    }
deba@2424
   251
deba@2424
   252
    /// \brief Sets the map storing the tree edges.
deba@2424
   253
    ///
deba@2424
   254
    /// Sets the map storing the tree edges.
deba@2424
   255
    /// If you don't use this function before calling \ref run(),
deba@2424
   256
    /// it will allocate one. The destuctor deallocates this
deba@2424
   257
    /// automatically allocated map, of course.
deba@2424
   258
    /// \return \c *this </tt>
deba@2424
   259
    Kruskal& treeMap(TreeMap &m){
deba@2424
   260
      if (local_tree) {
deba@2424
   261
	delete _tree;
deba@2424
   262
	local_tree = false;
deba@2424
   263
      }
deba@2424
   264
      _tree = &m;
deba@2424
   265
      return *this;
deba@2424
   266
    }
deba@2424
   267
deba@2424
   268
    /// \brief Initialize the algorithm
deba@2424
   269
    ///
deba@2424
   270
    /// This member function initializes the unionfind data structure
deba@2424
   271
    /// and sorts the edges into ascending order
deba@2424
   272
    void init() {
deba@2424
   273
      initStructures();
deba@2424
   274
      initUnionFind();
deba@2424
   275
      for (UEdgeIt e(graph); e != INVALID; ++e) {
deba@2424
   276
        edges.push_back(e);
deba@2424
   277
        _tree->set(e, false);
deba@2424
   278
      }      
deba@2424
   279
      Traits::sort(edges.begin(), edges.end(), cost); 
deba@2424
   280
      index = 0;
deba@2424
   281
    }
deba@2424
   282
deba@2424
   283
deba@2424
   284
    /// \brief Initialize the algorithm
deba@2424
   285
    ///
deba@2424
   286
    /// This member function initializes the unionfind data structure
deba@2424
   287
    /// and sets the edge order to the given sequence. The given
deba@2424
   288
    /// sequence should be a valid STL range of undirected edges.
deba@2424
   289
    template <typename Iterator>
deba@2424
   290
    void initPresorted(Iterator begin, Iterator end) {
deba@2424
   291
      initStructures();
deba@2424
   292
      initUnionFind();
deba@2424
   293
      edges.clear();
deba@2424
   294
      std::copy(begin, end, std::back_inserter(edges));
deba@2424
   295
      index = 0;
deba@2424
   296
    }
deba@2424
   297
deba@2424
   298
    /// \brief Initialize the algorithm
deba@2424
   299
    ///
deba@2424
   300
    /// This member function initializes the unionfind data structure
deba@2428
   301
    /// and sets the tree to empty. It does not change the order of
deba@2428
   302
    /// the edges, it uses the order of the previous running.
deba@2424
   303
    void reinit() {
deba@2424
   304
      initStructures();
deba@2424
   305
      initUnionFind();
deba@2424
   306
      for (UEdgeIt e(graph); e != INVALID; ++e) {
deba@2424
   307
        _tree->set(e, false);
deba@2424
   308
      }
deba@2424
   309
      index = 0;
deba@2424
   310
    }
deba@2424
   311
deba@2424
   312
deba@2424
   313
    /// \brief Executes the algorithm.
deba@2424
   314
    ///
deba@2424
   315
    /// Executes the algorithm.
deba@2424
   316
    ///
deba@2424
   317
    /// \pre init() must be called before using this function.
deba@2424
   318
    ///
deba@2424
   319
    /// This method runs the %Kruskal algorithm.
deba@2424
   320
    void start() {
deba@2424
   321
      while (index < int(edges.size())) {
deba@2424
   322
        if (uf->join(graph.target(edges[index]), graph.source(edges[index]))) {
deba@2424
   323
          _tree->set(edges[index], true);
deba@2424
   324
        }
deba@2424
   325
        ++index;
deba@2424
   326
      }
deba@2424
   327
    }
deba@2424
   328
deba@2424
   329
    /// \brief Runs the prim algorithm until it find a new tree edge
deba@2424
   330
    ///
deba@2424
   331
    /// Runs the prim algorithm until it find a new tree edge. If it
deba@2424
   332
    /// does not next tree edge in the sequence it gives back \c INVALID.
deba@2424
   333
    UEdge findNextTreeEdge() {
deba@2424
   334
      while (index < int(edges.size())) {
deba@2424
   335
        if (uf->join(graph.target(edges[index]), graph.source(edges[index]))) {
deba@2424
   336
          _tree->set(edges[index], true);
deba@2424
   337
          return edges[index++];
deba@2424
   338
        }        
deba@2424
   339
        ++index;
deba@2424
   340
      }
deba@2424
   341
      return INVALID;
deba@2424
   342
    }
deba@2424
   343
      
deba@2424
   344
    /// \brief Processes the next edge in the sequence
deba@2424
   345
    ///
deba@2424
   346
    /// Processes the next edge in the sequence.
deba@2424
   347
    ///
deba@2424
   348
    /// \return The prcocessed edge.
deba@2424
   349
    ///
deba@2424
   350
    /// \warning The sequence must not be empty!
deba@2424
   351
    UEdge processNextEdge() {
deba@2424
   352
      UEdge edge = edges[index++];
deba@2424
   353
      processEdge(edge);
deba@2424
   354
      return edge;
deba@2424
   355
    }
deba@2424
   356
deba@2424
   357
    /// \brief Processes an arbitrary edge
deba@2424
   358
    ///
deba@2424
   359
    /// Processes the next edge in the sequence.
deba@2424
   360
    ///
deba@2424
   361
    /// \return True when the edge is a tree edge.
deba@2424
   362
    bool processEdge(const UEdge& edge) {
deba@2424
   363
      if (uf->join(graph.target(edge), graph.source(edge))) {
deba@2424
   364
        _tree->set(edge, true);
deba@2424
   365
        return true;
deba@2424
   366
      } else {
deba@2424
   367
        return false;
deba@2424
   368
      }    
deba@2424
   369
    }
deba@2424
   370
deba@2424
   371
    /// \brief Returns \c false if there are edge to be processed in
deba@2424
   372
    /// sequence
deba@2424
   373
    ///
deba@2424
   374
    /// Returns \c false if there are nodes to be processed in the
deba@2424
   375
    /// sequence
deba@2424
   376
    bool emptyQueue() {
deba@2424
   377
      return index == int(edges.size());
deba@2424
   378
    }
deba@2424
   379
deba@2424
   380
    /// \brief Returns the next edge to be processed
deba@2424
   381
    ///
deba@2424
   382
    /// Returns the next edge to be processed
deba@2424
   383
    ///
deba@2424
   384
    UEdge nextEdge() const {
deba@2424
   385
      return edges[index];
deba@2424
   386
    }
deba@2424
   387
deba@2424
   388
    /// \brief Runs %Kruskal algorithm.
deba@2424
   389
    ///
deba@2424
   390
    /// This method runs the %Kruskal algorithm in order to compute the
deba@2424
   391
    /// minimum spanning tree (or minimum spanning forest).  The
deba@2424
   392
    /// method also works on graphs that has more than one components.
deba@2424
   393
    /// In this case it computes the minimum spanning forest.
deba@2424
   394
    void run() {
deba@2424
   395
      init();
deba@2424
   396
      start();
deba@2424
   397
    }
deba@2424
   398
deba@2424
   399
    /// \brief Returns a reference to the tree edges map
deba@2424
   400
    ///
deba@2424
   401
    /// Returns a reference to the TreeEdgeMap of the edges of the
deba@2424
   402
    /// minimum spanning tree. The value of the map is \c true only if
deba@2424
   403
    /// the edge is in the minimum spanning tree.
deba@2424
   404
    ///
deba@2424
   405
    const TreeMap &treeMap() const { return *_tree;}
deba@2424
   406
deba@2424
   407
    /// \brief Returns the total cost of the tree
deba@2424
   408
    ///
deba@2424
   409
    /// Returns the total cost of the tree
deba@2424
   410
    Value treeValue() const {
deba@2424
   411
      Value value = 0;
deba@2424
   412
      for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2424
   413
        if ((*_tree)[it]) {
deba@2424
   414
          value += cost[it];
deba@2424
   415
        }
deba@2424
   416
      }
deba@2424
   417
      return value;
deba@2424
   418
    }
deba@2424
   419
deba@2424
   420
    /// \brief Returns true when the given edge is tree edge
deba@2424
   421
    ///
deba@2424
   422
    /// Returns true when the given edge is tree edge
deba@2424
   423
    bool tree(UEdge e) const {
deba@2424
   424
      return (*_tree)[e];
deba@2424
   425
    }
deba@2424
   426
    
deba@2424
   427
    
deba@2424
   428
  };
deba@2424
   429
deba@2424
   430
deba@2424
   431
  namespace _kruskal_bits {
deba@2424
   432
deba@2424
   433
    template <typename Graph, typename In, typename Out>
deba@2424
   434
    typename In::value_type::second_type
deba@2424
   435
    kruskal(const Graph& graph, const In& in, Out& out) {
deba@2424
   436
      typedef typename In::value_type::second_type Value;
deba@2424
   437
      typedef typename Graph::template NodeMap<int> IndexMap;
deba@2424
   438
      typedef typename Graph::Node Node;
deba@2424
   439
      
deba@2424
   440
      IndexMap index(graph);
deba@2424
   441
      UnionFind<IndexMap> uf(index);
deba@2424
   442
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
deba@2424
   443
        uf.insert(it);
deba@2424
   444
      }
deba@2424
   445
      
deba@2424
   446
      Value tree_value = 0;
deba@2424
   447
      for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
deba@2424
   448
        if (uf.join(graph.target(it->first),graph.source(it->first))) {
deba@2424
   449
          out.set(it->first, true);
deba@2424
   450
          tree_value += it->second;
deba@2424
   451
        }
deba@2424
   452
        else {
deba@2424
   453
          out.set(it->first, false);
deba@2424
   454
        }
deba@2424
   455
      }
deba@2424
   456
      return tree_value;
deba@2424
   457
    }
deba@2424
   458
deba@2424
   459
deba@2424
   460
    template <typename Sequence>
deba@2424
   461
    struct PairComp {
deba@2424
   462
      typedef typename Sequence::value_type Value;
deba@2424
   463
      bool operator()(const Value& left, const Value& right) {
deba@2424
   464
	return left.second < right.second;
deba@2424
   465
      }
deba@2424
   466
    };
deba@2424
   467
deba@2424
   468
    template <typename In, typename Enable = void>
deba@2424
   469
    struct SequenceInputIndicator {
deba@2424
   470
      static const bool value = false;
deba@2424
   471
    };
deba@2424
   472
deba@2424
   473
    template <typename In>
deba@2424
   474
    struct SequenceInputIndicator<In, 
deba@2424
   475
      typename exists<typename In::value_type::first_type>::type> {
deba@2424
   476
      static const bool value = true;
deba@2424
   477
    };
deba@2424
   478
deba@2424
   479
    template <typename In, typename Enable = void>
deba@2424
   480
    struct MapInputIndicator {
deba@2424
   481
      static const bool value = false;
deba@2424
   482
    };
deba@2424
   483
deba@2424
   484
    template <typename In>
deba@2424
   485
    struct MapInputIndicator<In, 
deba@2424
   486
      typename exists<typename In::Value>::type> {
deba@2424
   487
      static const bool value = true;
deba@2424
   488
    };
deba@2424
   489
deba@2424
   490
    template <typename In, typename Enable = void>
deba@2424
   491
    struct SequenceOutputIndicator {
deba@2424
   492
      static const bool value = false;
deba@2424
   493
    };
deba@2424
   494
 
deba@2424
   495
    template <typename Out>
deba@2424
   496
    struct SequenceOutputIndicator<Out, 
deba@2424
   497
      typename exists<typename Out::value_type>::type> {
deba@2424
   498
      static const bool value = true;
deba@2424
   499
    };
deba@2424
   500
deba@2424
   501
    template <typename Out, typename Enable = void>
deba@2424
   502
    struct MapOutputIndicator {
deba@2424
   503
      static const bool value = false;
deba@2424
   504
    };
deba@2424
   505
deba@2424
   506
    template <typename Out>
deba@2424
   507
    struct MapOutputIndicator<Out, 
deba@2424
   508
      typename exists<typename Out::Value>::type> {
deba@2424
   509
      static const bool value = true;
deba@2424
   510
    };
deba@2424
   511
deba@2424
   512
    template <typename In, typename InEnable = void>
deba@2424
   513
    struct KruskalValueSelector {};
deba@2424
   514
deba@2424
   515
    template <typename In>
deba@2424
   516
    struct KruskalValueSelector<In,
deba@2424
   517
      typename enable_if<SequenceInputIndicator<In>, void>::type> 
deba@2424
   518
    {
deba@2424
   519
      typedef typename In::value_type::second_type Value;
deba@2424
   520
    };    
deba@2424
   521
deba@2424
   522
    template <typename In>
deba@2424
   523
    struct KruskalValueSelector<In,
deba@2424
   524
      typename enable_if<MapInputIndicator<In>, void>::type> 
deba@2424
   525
    {
deba@2424
   526
      typedef typename In::Value Value;
deba@2424
   527
    };    
deba@2424
   528
    
deba@2424
   529
    template <typename Graph, typename In, typename Out,
deba@2424
   530
              typename InEnable = void>
deba@2424
   531
    struct KruskalInputSelector {};
deba@2424
   532
deba@2424
   533
    template <typename Graph, typename In, typename Out,
deba@2424
   534
              typename InEnable = void>
deba@2424
   535
    struct KruskalOutputSelector {};
deba@2424
   536
    
deba@2424
   537
    template <typename Graph, typename In, typename Out>
deba@2424
   538
    struct KruskalInputSelector<Graph, In, Out,
deba@2424
   539
      typename enable_if<SequenceInputIndicator<In>, void>::type > 
deba@2424
   540
    {
deba@2424
   541
      typedef typename In::value_type::second_type Value;
deba@2424
   542
deba@2424
   543
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
deba@2424
   544
        return KruskalOutputSelector<Graph, In, Out>::
deba@2424
   545
          kruskal(graph, in, out);
deba@2424
   546
      }
deba@2424
   547
deba@2424
   548
    };
deba@2424
   549
deba@2424
   550
    template <typename Graph, typename In, typename Out>
deba@2424
   551
    struct KruskalInputSelector<Graph, In, Out,
deba@2424
   552
      typename enable_if<MapInputIndicator<In>, void>::type > 
deba@2424
   553
    {
deba@2424
   554
      typedef typename In::Value Value;
deba@2424
   555
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
deba@2424
   556
        typedef typename In::Key MapEdge;
deba@2424
   557
        typedef typename In::Value Value;
deba@2424
   558
        typedef typename ItemSetTraits<Graph, MapEdge>::ItemIt MapEdgeIt;
deba@2424
   559
        typedef std::vector<std::pair<MapEdge, Value> > Sequence;
deba@2424
   560
        Sequence seq;
deba@2424
   561
        
deba@2424
   562
        for (MapEdgeIt it(graph); it != INVALID; ++it) {
ladanyi@2431
   563
          seq.push_back(std::make_pair(it, in[it]));
deba@2424
   564
        }
deba@2424
   565
deba@2424
   566
        std::sort(seq.begin(), seq.end(), PairComp<Sequence>());
deba@2424
   567
        return KruskalOutputSelector<Graph, Sequence, Out>::
deba@2424
   568
          kruskal(graph, seq, out);
deba@2424
   569
      }
deba@2424
   570
    };
deba@2424
   571
deba@2424
   572
    template <typename Graph, typename In, typename Out>
deba@2424
   573
    struct KruskalOutputSelector<Graph, In, Out,
deba@2424
   574
      typename enable_if<SequenceOutputIndicator<Out>, void>::type > 
deba@2424
   575
    {
deba@2424
   576
      typedef typename In::value_type::second_type Value;
deba@2424
   577
deba@2424
   578
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
deba@2424
   579
        typedef StoreBoolMap<Out> Map;
deba@2424
   580
        Map map(out);
deba@2424
   581
        return _kruskal_bits::kruskal(graph, in, map);
deba@2424
   582
      }
deba@2424
   583
deba@2424
   584
    };
deba@2424
   585
deba@2424
   586
    template <typename Graph, typename In, typename Out>
deba@2424
   587
    struct KruskalOutputSelector<Graph, In, Out,
deba@2424
   588
      typename enable_if<MapOutputIndicator<Out>, void>::type > 
deba@2424
   589
    {
deba@2424
   590
      typedef typename In::value_type::second_type Value;
deba@2424
   591
deba@2424
   592
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
deba@2424
   593
        return _kruskal_bits::kruskal(graph, in, out);
deba@2424
   594
      }
deba@2424
   595
    };
deba@2424
   596
deba@2424
   597
  }
deba@2424
   598
deba@2424
   599
  /// \ingroup spantree
deba@2424
   600
  ///
deba@2424
   601
  /// \brief Kruskal's algorithm to find a minimum cost tree of a graph.
deba@2424
   602
  ///
alpar@810
   603
  /// This function runs Kruskal's algorithm to find a minimum cost tree.
alpar@1557
   604
  /// Due to hard C++ hacking, it accepts various input and output types.
alpar@1557
   605
  ///
alpar@1555
   606
  /// \param g The graph the algorithm runs on.
alpar@2260
   607
  /// It can be either \ref concepts::Graph "directed" or 
alpar@2260
   608
  /// \ref concepts::UGraph "undirected".
alpar@1555
   609
  /// If the graph is directed, the algorithm consider it to be 
alpar@1555
   610
  /// undirected by disregarding the direction of the edges.
alpar@810
   611
  ///
alpar@1557
   612
  /// \param in This object is used to describe the edge costs. It can be one
alpar@1557
   613
  /// of the following choices.
deba@2424
   614
  ///
deba@2424
   615
  /// - An STL compatible 'Forward Container' with
deba@2424
   616
  /// <tt>std::pair<GR::UEdge,X></tt> or
deba@2424
   617
  /// <tt>std::pair<GR::Edge,X></tt> as its <tt>value_type</tt>, where
deba@2424
   618
  /// \c X is the type of the costs. The pairs indicates the edges
deba@2424
   619
  /// along with the assigned cost. <em>They must be in a
alpar@1557
   620
  /// cost-ascending order.</em>
alpar@1557
   621
  /// - Any readable Edge map. The values of the map indicate the edge costs.
alpar@810
   622
  ///
alpar@1557
   623
  /// \retval out Here we also have a choise.
deba@2424
   624
  /// - It can be a writable \c bool edge map.  After running the
deba@2424
   625
  /// algorithm this will contain the found minimum cost spanning
deba@2424
   626
  /// tree: the value of an edge will be set to \c true if it belongs
deba@2424
   627
  /// to the tree, otherwise it will be set to \c false. The value of
deba@2424
   628
  /// each edge will be set exactly once.
alpar@1557
   629
  /// - It can also be an iteraror of an STL Container with
deba@2424
   630
  /// <tt>GR::UEdge</tt> or <tt>GR::Edge</tt> as its
deba@2424
   631
  /// <tt>value_type</tt>.  The algorithm copies the elements of the
deba@2424
   632
  /// found tree into this sequence.  For example, if we know that the
deba@2424
   633
  /// spanning tree of the graph \c g has say 53 edges, then we can
deba@2424
   634
  /// put its edges into an STL vector \c tree with a code like this.
alpar@1946
   635
  ///\code
alpar@1557
   636
  /// std::vector<Edge> tree(53);
alpar@1557
   637
  /// kruskal(g,cost,tree.begin());
alpar@1946
   638
  ///\endcode
deba@2424
   639
  /// Or if we don't know in advance the size of the tree, we can
deba@2424
   640
  /// write this.  
deba@2424
   641
  ///\code std::vector<Edge> tree;
deba@2424
   642
  /// kruskal(g,cost,std::back_inserter(tree)); 
alpar@1946
   643
  ///\endcode
alpar@810
   644
  ///
deba@2424
   645
  /// \return The total cost of the found tree.
alpar@1449
   646
  ///
deba@2424
   647
  /// \warning If kruskal runs on an be consistent of using the same
deba@2424
   648
  /// Edge type for input and output.
alpar@1603
   649
  ///
alpar@810
   650
alpar@1557
   651
#ifdef DOXYGEN
deba@2424
   652
  template <class Graph, class In, class Out>
deba@2424
   653
  Value kruskal(GR const& g, const In& in, Out& out)
deba@2424
   654
#else 
deba@2424
   655
  template <class Graph, class In, class Out>
deba@2424
   656
  inline typename _kruskal_bits::KruskalValueSelector<In>::Value 
deba@2424
   657
  kruskal(const Graph& graph, const In& in, Out& out) 
alpar@1557
   658
#endif
alpar@810
   659
  {
deba@2424
   660
    return _kruskal_bits::KruskalInputSelector<Graph, In, Out>::
deba@2424
   661
      kruskal(graph, in, out);
alpar@810
   662
  }
alpar@810
   663
alpar@1557
   664
 
alpar@810
   665
  
klao@885
   666
deba@2424
   667
  template <class Graph, class In, class Out>
deba@2424
   668
  inline typename _kruskal_bits::KruskalValueSelector<In>::Value
deba@2424
   669
  kruskal(const Graph& graph, const In& in, const Out& out)
alpar@1557
   670
  {
deba@2424
   671
    return _kruskal_bits::KruskalInputSelector<Graph, In, const Out>::
deba@2424
   672
      kruskal(graph, in, out);
deba@2424
   673
  }  
alpar@810
   674
alpar@921
   675
} //namespace lemon
alpar@810
   676
alpar@921
   677
#endif //LEMON_KRUSKAL_H