//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//
#ifndef BOOST_GRAPH_MST_KRUSKAL_HPP
#define BOOST_GRAPH_MST_KRUSKAL_HPP

/*
 *Minimum Spanning Tree 
 *         Kruskal Algorithm
 *
 *Requirement:
 *      undirected graph
 */

#include <vector>
#include <queue>
#include <functional>

#include <boost/property_map/property_map.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/pending/disjoint_sets.hpp>
#include <boost/pending/indirect_cmp.hpp>


namespace boost {

  // Kruskal's algorithm for Minimum Spanning Tree
  //
  // This is a greedy algorithm to calculate the Minimum Spanning Tree
  // for an undirected graph with weighted edges. The output will be a
  // set of edges.
  //

  namespace detail {

    template <class Graph, class OutputIterator, 
              class Rank, class Parent, class Weight>
    void
    kruskal_mst_impl(const Graph& G, 
                     OutputIterator spanning_tree_edges, 
                     Rank rank, Parent parent, Weight weight)
    {
      if (num_vertices(G) == 0) return; // Nothing to do in this case
      typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
      typedef typename graph_traits<Graph>::edge_descriptor Edge;
      function_requires<VertexListGraphConcept<Graph> >();
      function_requires<EdgeListGraphConcept<Graph> >();
      function_requires<OutputIteratorConcept<OutputIterator, Edge> >();
      function_requires<ReadWritePropertyMapConcept<Rank, Vertex> >();
      function_requires<ReadWritePropertyMapConcept<Parent, Vertex> >();
      function_requires<ReadablePropertyMapConcept<Weight, Edge> >();
      typedef typename property_traits<Weight>::value_type W_value;
      typedef typename property_traits<Rank>::value_type R_value;
      typedef typename property_traits<Parent>::value_type P_value;
      function_requires<ComparableConcept<W_value> >();
      function_requires<ConvertibleConcept<P_value, Vertex> >();
      function_requires<IntegerConcept<R_value> >();

      disjoint_sets<Rank, Parent>  dset(rank, parent);

      typename graph_traits<Graph>::vertex_iterator ui, uiend;
      for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui)
        dset.make_set(*ui);

      typedef indirect_cmp<Weight, std::greater<W_value> > weight_greater;
      weight_greater wl(weight);
      std::priority_queue<Edge, std::vector<Edge>, weight_greater> Q(wl);
      /*push all edge into Q*/
      typename graph_traits<Graph>::edge_iterator ei, eiend;
      for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei) 
        Q.push(*ei);

      while (! Q.empty()) {
        Edge e = Q.top();
        Q.pop();
        Vertex u = dset.find_set(source(e, G));
        Vertex v = dset.find_set(target(e, G));
        if ( u != v ) {
          *spanning_tree_edges++ = e;
          dset.link(u, v);
        }
      }
    }

  } // namespace detail 

  // Named Parameters Variants

  template <class Graph, class OutputIterator>
  inline void 
  kruskal_minimum_spanning_tree(const Graph& g,
                                OutputIterator spanning_tree_edges)
  {
    typedef typename graph_traits<Graph>::vertices_size_type size_type;
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename property_map<Graph, vertex_index_t>::type index_map_t;
    if (num_vertices(g) == 0) return; // Nothing to do in this case
    typename graph_traits<Graph>::vertices_size_type
      n = num_vertices(g);
    std::vector<size_type> rank_map(n);
    std::vector<vertex_t> pred_map(n);

    detail::kruskal_mst_impl
      (g, spanning_tree_edges, 
       make_iterator_property_map(rank_map.begin(), get(vertex_index, g), rank_map[0]),
       make_iterator_property_map(pred_map.begin(), get(vertex_index, g), pred_map[0]),
       get(edge_weight, g));
  }

  template <class Graph, class OutputIterator, class P, class T, class R>
  inline void
  kruskal_minimum_spanning_tree(const Graph& g,
                                OutputIterator spanning_tree_edges, 
                                const bgl_named_params<P, T, R>& params)
  {
    typedef typename graph_traits<Graph>::vertices_size_type size_type;
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    if (num_vertices(g) == 0) return; // Nothing to do in this case
    typename graph_traits<Graph>::vertices_size_type n;
    n = is_default_param(get_param(params, vertex_rank))
                                   ? num_vertices(g) : 1;
    std::vector<size_type> rank_map(n);
    n = is_default_param(get_param(params, vertex_predecessor))
                                   ? num_vertices(g) : 1;
    std::vector<vertex_t> pred_map(n);
    
    detail::kruskal_mst_impl
      (g, spanning_tree_edges, 
       choose_param
       (get_param(params, vertex_rank), 
        make_iterator_property_map
        (rank_map.begin(), 
         choose_pmap(get_param(params, vertex_index), g, vertex_index), rank_map[0])),
       choose_param
       (get_param(params, vertex_predecessor), 
        make_iterator_property_map
        (pred_map.begin(), 
         choose_const_pmap(get_param(params, vertex_index), g, vertex_index), 
         pred_map[0])),
       choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
  }
    
} // namespace boost


#endif // BOOST_GRAPH_MST_KRUSKAL_HPP

