kruskal_min_spanning_tree.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //
  2. //=======================================================================
  3. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  4. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //=======================================================================
  10. //
  11. #ifndef BOOST_GRAPH_MST_KRUSKAL_HPP
  12. #define BOOST_GRAPH_MST_KRUSKAL_HPP
  13. /*
  14. *Minimum Spanning Tree
  15. * Kruskal Algorithm
  16. *
  17. *Requirement:
  18. * undirected graph
  19. */
  20. #include <vector>
  21. #include <queue>
  22. #include <functional>
  23. #include <boost/property_map/property_map.hpp>
  24. #include <boost/graph/graph_concepts.hpp>
  25. #include <boost/graph/named_function_params.hpp>
  26. #include <boost/pending/disjoint_sets.hpp>
  27. #include <boost/pending/indirect_cmp.hpp>
  28. #include <boost/concept/assert.hpp>
  29. namespace boost {
  30. // Kruskal's algorithm for Minimum Spanning Tree
  31. //
  32. // This is a greedy algorithm to calculate the Minimum Spanning Tree
  33. // for an undirected graph with weighted edges. The output will be a
  34. // set of edges.
  35. //
  36. namespace detail {
  37. template <class Graph, class OutputIterator,
  38. class Rank, class Parent, class Weight>
  39. void
  40. kruskal_mst_impl(const Graph& G,
  41. OutputIterator spanning_tree_edges,
  42. Rank rank, Parent parent, Weight weight)
  43. {
  44. if (num_vertices(G) == 0) return; // Nothing to do in this case
  45. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  46. typedef typename graph_traits<Graph>::edge_descriptor Edge;
  47. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
  48. BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> ));
  49. BOOST_CONCEPT_ASSERT(( OutputIteratorConcept<OutputIterator, Edge> ));
  50. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<Rank, Vertex> ));
  51. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<Parent, Vertex> ));
  52. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<Weight, Edge> ));
  53. typedef typename property_traits<Weight>::value_type W_value;
  54. typedef typename property_traits<Rank>::value_type R_value;
  55. typedef typename property_traits<Parent>::value_type P_value;
  56. BOOST_CONCEPT_ASSERT(( ComparableConcept<W_value> ));
  57. BOOST_CONCEPT_ASSERT(( ConvertibleConcept<P_value, Vertex> ));
  58. BOOST_CONCEPT_ASSERT(( IntegerConcept<R_value> ));
  59. disjoint_sets<Rank, Parent> dset(rank, parent);
  60. typename graph_traits<Graph>::vertex_iterator ui, uiend;
  61. for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui)
  62. dset.make_set(*ui);
  63. typedef indirect_cmp<Weight, std::greater<W_value> > weight_greater;
  64. weight_greater wl(weight);
  65. std::priority_queue<Edge, std::vector<Edge>, weight_greater> Q(wl);
  66. /*push all edge into Q*/
  67. typename graph_traits<Graph>::edge_iterator ei, eiend;
  68. for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei)
  69. Q.push(*ei);
  70. while (! Q.empty()) {
  71. Edge e = Q.top();
  72. Q.pop();
  73. Vertex u = dset.find_set(source(e, G));
  74. Vertex v = dset.find_set(target(e, G));
  75. if ( u != v ) {
  76. *spanning_tree_edges++ = e;
  77. dset.link(u, v);
  78. }
  79. }
  80. }
  81. } // namespace detail
  82. // Named Parameters Variants
  83. template <class Graph, class OutputIterator>
  84. inline void
  85. kruskal_minimum_spanning_tree(const Graph& g,
  86. OutputIterator spanning_tree_edges)
  87. {
  88. typedef typename graph_traits<Graph>::vertices_size_type size_type;
  89. typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
  90. if (num_vertices(g) == 0) return; // Nothing to do in this case
  91. typename graph_traits<Graph>::vertices_size_type
  92. n = num_vertices(g);
  93. std::vector<size_type> rank_map(n);
  94. std::vector<vertex_t> pred_map(n);
  95. detail::kruskal_mst_impl
  96. (g, spanning_tree_edges,
  97. make_iterator_property_map(rank_map.begin(), get(vertex_index, g), rank_map[0]),
  98. make_iterator_property_map(pred_map.begin(), get(vertex_index, g), pred_map[0]),
  99. get(edge_weight, g));
  100. }
  101. template <class Graph, class OutputIterator, class P, class T, class R>
  102. inline void
  103. kruskal_minimum_spanning_tree(const Graph& g,
  104. OutputIterator spanning_tree_edges,
  105. const bgl_named_params<P, T, R>& params)
  106. {
  107. typedef typename graph_traits<Graph>::vertices_size_type size_type;
  108. typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
  109. if (num_vertices(g) == 0) return; // Nothing to do in this case
  110. typename graph_traits<Graph>::vertices_size_type n;
  111. n = is_default_param(get_param(params, vertex_rank))
  112. ? num_vertices(g) : 1;
  113. std::vector<size_type> rank_map(n);
  114. n = is_default_param(get_param(params, vertex_predecessor))
  115. ? num_vertices(g) : 1;
  116. std::vector<vertex_t> pred_map(n);
  117. detail::kruskal_mst_impl
  118. (g, spanning_tree_edges,
  119. choose_param
  120. (get_param(params, vertex_rank),
  121. make_iterator_property_map
  122. (rank_map.begin(),
  123. choose_pmap(get_param(params, vertex_index), g, vertex_index), rank_map[0])),
  124. choose_param
  125. (get_param(params, vertex_predecessor),
  126. make_iterator_property_map
  127. (pred_map.begin(),
  128. choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
  129. pred_map[0])),
  130. choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
  131. }
  132. } // namespace boost
  133. #endif // BOOST_GRAPH_MST_KRUSKAL_HPP