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 williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include 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 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::vertex_descriptor Vertex; williamr@2: typedef typename graph_traits::edge_descriptor Edge; williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: typedef typename property_traits::value_type W_value; williamr@2: typedef typename property_traits::value_type R_value; williamr@2: typedef typename property_traits::value_type P_value; williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: function_requires >(); williamr@2: williamr@2: disjoint_sets dset(rank, parent); williamr@2: williamr@2: typename graph_traits::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_greater; williamr@2: weight_greater wl(weight); williamr@2: std::priority_queue, weight_greater> Q(wl); williamr@2: /*push all edge into Q*/ williamr@2: typename graph_traits::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 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::vertices_size_type size_type; williamr@2: typedef typename graph_traits::vertex_descriptor vertex_t; williamr@2: typedef typename property_map::type index_map_t; williamr@2: if (num_vertices(g) == 0) return; // Nothing to do in this case williamr@2: typename graph_traits::vertices_size_type williamr@2: n = num_vertices(g); williamr@2: std::vector rank_map(n); williamr@2: std::vector 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 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& params) williamr@2: { williamr@2: typedef typename graph_traits::vertices_size_type size_type; williamr@2: typedef typename graph_traits::vertex_descriptor vertex_t; williamr@2: if (num_vertices(g) == 0) return; // Nothing to do in this case williamr@2: typename graph_traits::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 rank_map(n); williamr@2: n = is_default_param(get_param(params, vertex_predecessor)) williamr@2: ? num_vertices(g) : 1; williamr@2: std::vector 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: