src/work/johanna/kruskal.h
author alpar
Fri, 03 Sep 2004 14:26:03 +0000
changeset 797 a76d8d52b25c
parent 755 a8c2e828ce0b
permissions -rw-r--r--
Skeleton for paths.
     1 // -*- c++ -*- //
     2 #ifndef HUGO_KRUSKAL_H
     3 #define HUGO_KRUSKAL_H
     4 
     5 #include <algorithm>
     6 #include <hugo/unionfind.h>
     7 
     8 /**
     9 @defgroup spantree Minimum Cost Spanning Tree Algorithms
    10 \brief This group containes the algorithms for finding a minimum cost spanning
    11 tree in a graph
    12 @ingroup galgs
    13 */
    14 
    15 ///\ingroup spantree
    16 ///\file
    17 ///\brief Kruskal's algorithm to compute a minimum cost tree
    18 
    19 namespace hugo {
    20 
    21   /// \addtogroup spantree
    22   /// @{
    23 
    24   /// Kruskal's algorithm to find a minimum cost tree of a graph.
    25 
    26   /// This function runs Kruskal's algorithm to find a minimum cost tree.
    27   /// \param G The graph the algorithm runs on.
    28   /// \param in This object is used to describe the edge costs. It must
    29   /// be an STL 'forward container'
    30   /// with value_type <tt> std::pair<Graph::Edge,X> </tt>,
    31   /// where X is the type of the costs. It must contain every edge in
    32   /// cost-ascending order.
    33   /// \retval out This must be a writeable EdgeMap. After running the algorithm
    34   /// this will contain the found minimum cost spanning tree: the value of an
    35   /// edge will be set to \c true if it belongs to the tree, otherwise it will
    36   /// be set to \c false. The value of each edge will be set exactly once.\n
    37   /// For the sake of simplicity, there is a helper class KruskalPairVec,
    38   /// which converts a
    39   /// simple EdgeMap to an input of this form. Alternatively, you can use
    40   /// the function \ref kruskalEdgeMap to compute the minimum cost tree if
    41   /// the edge costs are given by an EdgeMap.
    42   /// \return The cost of the found tree.
    43 
    44   template <typename Graph, typename InputEdgeOrder, typename OutBoolMap>
    45   typename InputEdgeOrder::value_type::second_type
    46   kruskal(Graph const& G, InputEdgeOrder const& in, 
    47 		 OutBoolMap& out)
    48   {
    49     typedef typename InputEdgeOrder::value_type::second_type EdgeCost;
    50     typedef typename Graph::template NodeMap<int> NodeIntMap;
    51     typedef typename Graph::Node Node;
    52 
    53     NodeIntMap comp(G, -1);
    54     UnionFind<Node,NodeIntMap> uf(comp); 
    55       
    56     EdgeCost tot_cost = 0;
    57     for (typename InputEdgeOrder::const_iterator p = in.begin(); 
    58 	 p!=in.end(); ++p ) {
    59       if ( uf.join(G.head((*p).first),
    60 		   G.tail((*p).first)) ) {
    61 	out.set((*p).first, true);
    62 	tot_cost += (*p).second;
    63       }
    64       else {
    65 	out.set((*p).first, false);
    66       }
    67     }
    68     return tot_cost;
    69   }
    70 
    71   /* A work-around for running Kruskal with const-reference bool maps... */
    72 
    73   template<typename Map>
    74   class NonConstMapWr {
    75     const Map &m;
    76   public:
    77     typedef typename Map::ValueType ValueType;
    78 
    79     NonConstMapWr(const Map &_m) : m(_m) {}
    80 
    81     template<typename KeyType>
    82     void set(KeyType const& k, ValueType const &v) const { m.set(k,v); }
    83   };
    84 
    85   template <typename Graph, typename InputEdgeOrder, typename OutBoolMap>
    86   inline
    87   typename InputEdgeOrder::ValueType
    88   kruskal(Graph const& G, InputEdgeOrder const& edges, 
    89 	  OutBoolMap const& out_map)
    90   {
    91     NonConstMapWr<OutBoolMap> map_wr(out_map);
    92     return kruskal(G, edges, map_wr);
    93   }  
    94 
    95   
    96   /* ** ** Output-objektumok: egyszeruen extra bool mapek ** ** */
    97   
    98   /// A writable bool-map that makes a sequence of "true" keys
    99 
   100   /// A writable bool-map that creates a sequence out of keys that receives
   101   /// the value "true".
   102   /// \warning Not a regular property map, as it doesn't know its KeyType
   103 
   104   template<typename Iterator>
   105   class SequenceOutput {
   106     mutable Iterator it;
   107 
   108   public:
   109     typedef bool ValueType;
   110 
   111     SequenceOutput(Iterator const &_it) : it(_it) {}
   112 
   113     template<typename KeyType>
   114     void set(KeyType const& k, bool v) const { if(v) {*it=k; ++it;} }
   115   };
   116 
   117   template<typename Iterator>
   118   inline
   119   SequenceOutput<Iterator>
   120   makeSequenceOutput(Iterator it) {
   121     return SequenceOutput<Iterator>(it);
   122   }
   123 
   124   /* ** ** InputSource -ok ** ** */
   125 
   126   /// Kruskal input source.
   127 
   128   /// Kruskal input source.
   129   ///
   130   template<typename Graph, typename Map>
   131   class KruskalMapInput
   132     : public std::vector< std::pair<typename Graph::Edge,
   133 				    typename Map::ValueType> > {
   134     
   135   public:
   136     typedef std::vector< std::pair<typename Graph::Edge,
   137 				   typename Map::ValueType> > Parent;
   138     typedef typename Parent::value_type value_type;
   139 //     typedef Key KeyType;
   140 //     typedef Val ValueType;
   141 //     typedef std::pair<Key,Val> PairType;
   142 //     typedef typename Parent::iterator iterator;
   143 //     typedef typename Parent::const_iterator const_iterator;
   144 
   145   private:
   146     class comparePair {
   147     public:
   148       bool operator()(const value_type& a,
   149 		      const value_type& b) {
   150 	return a.second < b.second;
   151       }
   152     };
   153 
   154   public:
   155 
   156     // FIXME: kell ez?
   157     // KruskalMapInput(Parent const& p) : Parent(p) {}
   158     
   159     void sort() {
   160       std::sort(this->begin(), this->end(), comparePair());
   161     }
   162 
   163     // FIXME: nem nagyon illik ez ide...
   164     KruskalMapInput(Graph const& G, Map const& m) {
   165       typedef typename Graph::EdgeIt EdgeIt;
   166       
   167       this->clear();
   168       for(EdgeIt e(G);G.valid(e);G.next(e)) {
   169 	// for (EdgeIt e=G.template first<EdgeIt>(); G.valid(e); G.next(e)) {
   170 	push_back(make_pair(e, m[e]));
   171       }
   172       sort();
   173     }
   174 
   175 //     Key const& first(const_iterator i) const { return i->first; }
   176 //     Key& first(iterator i) { return i->first; }
   177 
   178 //     Val const& second(const_iterator i) const { return i->second; }
   179 //     Val& second(iterator i) { return i->second; }
   180   };
   181 
   182 
   183 //   template<typename Graph, typename Map>
   184 //   class KruskalMapVec {
   185 //   public:
   186     
   187 //     typedef std::pair<typename Map::KeyType, Map::ValueType> value_type;
   188     
   189 //     typedef std::vector<KeyType> Container;
   190 //     Container container;
   191 //     std::vector<typename Map::KeyType> container
   192 //     const Map &m;
   193     
   194     
   195 //     class iterator
   196 //     {
   197 //       Container::iterator i;
   198 //     public:
   199 //       iterator &operator ++() {++i;return *this;}
   200 //       valuetype operator *() {return value_type(container(i),m[container(i)]);}
   201 //       bool operator==(iterator b) {return i==b.i;}
   202 //       iterator() {}
   203 //       iterator(Container::iterator _i) i(_i) {}
   204 //     };
   205 //     class const_iterator
   206 //     {
   207 //       Container::const_iterator i;
   208 //     public:
   209 //       iterator &operator ++() {++i;return *this;}
   210 //       valuetype operator *() {return value_type(container(i),m[container(i)]);}
   211 //       bool operator==(iterator b) {return i==b.i;}
   212 //       const_iterator() {}
   213 //       const_iterator(Container::iterator _i) i(_i) {}
   214 //     };
   215 
   216 //     iterator begin() { return iterator(container.begin());}
   217 //     const_iterator begin() const { return iterator(container.begin());}
   218 //     iterator end() { return iterator(container.end());}
   219 //     const_iterator end() const { return iterator(container.end());}
   220     
   221 //   private:
   222     
   223 //     class compareKeys {
   224 //       const Map &m;
   225 //     public:
   226 //       compareKeys(Map const &_m) : m(_m) {}
   227 //       bool operator()(KeyType const& a, KeyType const& b) {
   228 // 	return m[a] < m[b];
   229 //       }
   230 //     };
   231 
   232 //   public:
   233 
   234 //     KruskalMapVec(Map const& _m) : m(_m) {}
   235 
   236 //     void sort() {
   237 //       std::sort(begin(), end(), compareKeys(m));
   238 //     }
   239 
   240 //     // FIXME: nem nagyon illik ez ide...
   241 //     template<typename Graph>
   242 //     KruskalMapVec(Graph const& G, Map const& _m) : m(_m) {
   243 //       typedef typename Graph::EdgeIt EdgeIt;
   244 
   245 //       clear();
   246 //       for(EdgeIt e(G);G.valid(e);G.next(e)) {
   247 //       // for (EdgeIt e=G.template first<EdgeIt>(); G.valid(e); G.next(e)) 
   248 // 	push_back(e);
   249 //       }
   250 //       sort();
   251 //     }
   252 
   253 //     KeyType const& first(const_iterator i) const { return *i; }
   254 //     KeyType& first(iterator i) { return *i; }
   255 
   256 //     ValueType const& second(const_iterator i) const { return m[*i]; }
   257 //     ValueType& second(iterator i) { return m[*i]; }
   258 //   };
   259 
   260 
   261   /* ** ** Wrapper fuggvenyek ** ** */
   262 
   263 
   264   /// \brief Wrapper to Kruskal().
   265   /// Input is from an EdgeMap, output is a plain boolmap.
   266 
   267   ///\todo some more words would be nice here.
   268   ///
   269   template <typename Graph, typename EdgeCostMap, typename RetEdgeBoolMap>
   270   inline
   271   typename EdgeCostMap::ValueType
   272   kruskalEdgeMap(Graph const& G,
   273 			EdgeCostMap const& edge_costs,
   274 			RetEdgeBoolMap &ret_bool_map) {
   275     
   276     typedef KruskalMapInput<Graph,EdgeCostMap> InputVec;
   277     
   278     InputVec iv(G, edge_costs);
   279     return kruskal(G, iv, ret_bool_map);
   280   }
   281 
   282 
   283   /// \brief Wrapper to Kruskal().
   284   /// Input is from an EdgeMap, output is to a sequence.
   285 
   286   ///\todo it does not follow the naming convention.
   287   ///
   288   template <typename Graph, typename EdgeCostMap, typename RetIterator>
   289   inline
   290   typename EdgeCostMap::ValueType
   291   kruskalEdgeMap_IteratorOut(const Graph& G,
   292 			     const EdgeCostMap& edge_costs,
   293 			     RetIterator ret_iterator)
   294   {
   295     typedef typename EdgeCostMap::ValueType ValueType;
   296     
   297     typedef SequenceOutput<RetIterator> OutMap;
   298     OutMap out(ret_iterator);
   299 
   300     typedef KruskalMapInput<Graph, EdgeCostMap> InputVec;
   301 
   302     InputVec iv(G, edge_costs);
   303 
   304     return kruskal(G, iv, out);
   305   }
   306 
   307   /// @}
   308 
   309 } //namespace hugo
   310 
   311 #endif //HUGO_KRUSKAL_H