williamr@2: // williamr@2: //======================================================================= williamr@2: // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. williamr@2: // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: //======================================================================= williamr@2: // williamr@2: #ifndef BOOST_GRAPH_MST_KRUSKAL_HPP williamr@2: #define BOOST_GRAPH_MST_KRUSKAL_HPP williamr@2: williamr@2: /* williamr@2: *Minimum Spanning Tree williamr@2: * Kruskal Algorithm williamr@2: * williamr@2: *Requirement: williamr@2: * undirected graph williamr@2: */ williamr@2: williamr@2: #include <vector> williamr@2: #include <queue> williamr@2: #include <functional> williamr@2: williamr@2: #include <boost/property_map.hpp> williamr@2: #include <boost/graph/graph_concepts.hpp> williamr@2: #include <boost/graph/named_function_params.hpp> williamr@2: #include <boost/pending/disjoint_sets.hpp> williamr@2: #include <boost/pending/indirect_cmp.hpp> williamr@2: williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: // Kruskal's algorithm for Minimum Spanning Tree williamr@2: // williamr@2: // This is a greedy algorithm to calculate the Minimum Spanning Tree williamr@2: // for an undirected graph with weighted edges. The output will be a williamr@2: // set of edges. williamr@2: // williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: template <class Graph, class OutputIterator, williamr@2: class Rank, class Parent, class Weight> williamr@2: void williamr@2: kruskal_mst_impl(const Graph& G, williamr@2: OutputIterator spanning_tree_edges, williamr@2: Rank rank, Parent parent, Weight weight) williamr@2: { williamr@2: if (num_vertices(G) == 0) return; // Nothing to do in this case williamr@2: typedef typename graph_traits<Graph>::vertex_descriptor Vertex; williamr@2: typedef typename graph_traits<Graph>::edge_descriptor Edge; williamr@2: function_requires<VertexListGraphConcept<Graph> >(); williamr@2: function_requires<EdgeListGraphConcept<Graph> >(); williamr@2: function_requires<OutputIteratorConcept<OutputIterator, Edge> >(); williamr@2: function_requires<ReadWritePropertyMapConcept<Rank, Vertex> >(); williamr@2: function_requires<ReadWritePropertyMapConcept<Parent, Vertex> >(); williamr@2: function_requires<ReadablePropertyMapConcept<Weight, Edge> >(); williamr@2: typedef typename property_traits<Weight>::value_type W_value; williamr@2: typedef typename property_traits<Rank>::value_type R_value; williamr@2: typedef typename property_traits<Parent>::value_type P_value; williamr@2: function_requires<ComparableConcept<W_value> >(); williamr@2: function_requires<ConvertibleConcept<P_value, Vertex> >(); williamr@2: function_requires<IntegerConcept<R_value> >(); williamr@2: williamr@2: disjoint_sets<Rank, Parent> dset(rank, parent); williamr@2: williamr@2: typename graph_traits<Graph>::vertex_iterator ui, uiend; williamr@2: for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui) williamr@2: dset.make_set(*ui); williamr@2: williamr@2: typedef indirect_cmp<Weight, std::greater<W_value> > weight_greater; williamr@2: weight_greater wl(weight); williamr@2: std::priority_queue<Edge, std::vector<Edge>, weight_greater> Q(wl); williamr@2: /*push all edge into Q*/ williamr@2: typename graph_traits<Graph>::edge_iterator ei, eiend; williamr@2: for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei) williamr@2: Q.push(*ei); williamr@2: williamr@2: while (! Q.empty()) { williamr@2: Edge e = Q.top(); williamr@2: Q.pop(); williamr@2: Vertex u = dset.find_set(source(e, G)); williamr@2: Vertex v = dset.find_set(target(e, G)); williamr@2: if ( u != v ) { williamr@2: *spanning_tree_edges++ = e; williamr@2: dset.link(u, v); williamr@2: } williamr@2: } williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: // Named Parameters Variants williamr@2: williamr@2: template <class Graph, class OutputIterator> williamr@2: inline void williamr@2: kruskal_minimum_spanning_tree(const Graph& g, williamr@2: OutputIterator spanning_tree_edges) williamr@2: { williamr@2: typedef typename graph_traits<Graph>::vertices_size_type size_type; williamr@2: typedef typename graph_traits<Graph>::vertex_descriptor vertex_t; williamr@2: typedef typename property_map<Graph, vertex_index_t>::type index_map_t; williamr@2: if (num_vertices(g) == 0) return; // Nothing to do in this case williamr@2: typename graph_traits<Graph>::vertices_size_type williamr@2: n = num_vertices(g); williamr@2: std::vector<size_type> rank_map(n); williamr@2: std::vector<vertex_t> pred_map(n); williamr@2: williamr@2: detail::kruskal_mst_impl williamr@2: (g, spanning_tree_edges, williamr@2: make_iterator_property_map(rank_map.begin(), get(vertex_index, g), rank_map[0]), williamr@2: make_iterator_property_map(pred_map.begin(), get(vertex_index, g), pred_map[0]), williamr@2: get(edge_weight, g)); williamr@2: } williamr@2: williamr@2: template <class Graph, class OutputIterator, class P, class T, class R> williamr@2: inline void williamr@2: kruskal_minimum_spanning_tree(const Graph& g, williamr@2: OutputIterator spanning_tree_edges, williamr@2: const bgl_named_params<P, T, R>& params) williamr@2: { williamr@2: typedef typename graph_traits<Graph>::vertices_size_type size_type; williamr@2: typedef typename graph_traits<Graph>::vertex_descriptor vertex_t; williamr@2: if (num_vertices(g) == 0) return; // Nothing to do in this case williamr@2: typename graph_traits<Graph>::vertices_size_type n; williamr@2: n = is_default_param(get_param(params, vertex_rank)) williamr@2: ? num_vertices(g) : 1; williamr@2: std::vector<size_type> rank_map(n); williamr@2: n = is_default_param(get_param(params, vertex_predecessor)) williamr@2: ? num_vertices(g) : 1; williamr@2: std::vector<vertex_t> pred_map(n); williamr@2: williamr@2: detail::kruskal_mst_impl williamr@2: (g, spanning_tree_edges, williamr@2: choose_param williamr@2: (get_param(params, vertex_rank), williamr@2: make_iterator_property_map williamr@2: (rank_map.begin(), williamr@2: choose_pmap(get_param(params, vertex_index), g, vertex_index), rank_map[0])), williamr@2: choose_param williamr@2: (get_param(params, vertex_predecessor), williamr@2: make_iterator_property_map williamr@2: (pred_map.begin(), williamr@2: choose_const_pmap(get_param(params, vertex_index), g, vertex_index), williamr@2: pred_map[0])), williamr@2: choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); williamr@2: } williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: williamr@2: #endif // BOOST_GRAPH_MST_KRUSKAL_HPP williamr@2: