In C++98 array size shall be an integral constant expression. Fixes
ticket 12.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_FREDMAN_TARJAN_H
20 #define LEMON_FREDMAN_TARJAN_H
24 ///\brief FredmanTarjan algorithm to compute minimum spanning forest.
29 #include <lemon/list_graph.h>
30 #include <lemon/smart_graph.h>
31 #include <lemon/fib_heap.h>
32 #include <lemon/radix_sort.h>
33 #include <lemon/bits/invalid.h>
34 #include <lemon/error.h>
35 #include <lemon/maps.h>
36 #include <lemon/bits/traits.h>
37 #include <lemon/graph_utils.h>
39 #include <lemon/concepts/ugraph.h>
43 ///Default traits class of FredmanTarjan class.
45 ///Default traits class of FredmanTarjan class.
46 ///\param GR Graph type.
47 ///\param CM Type of cost map.
48 template<class GR, class CM>
49 struct FredmanTarjanDefaultTraits{
50 ///The graph type the algorithm runs on.
52 ///The type of the map that stores the edge costs.
54 ///The type of the map that stores the edge costs.
55 ///It must meet the \ref concepts::ReadMap "ReadMap" concept.
57 //The type of the cost of the edges.
58 typedef typename CM::Value Value;
59 ///The type of the map that stores whether an edge is in the
60 ///spanning tree or not.
62 ///The type of the map that stores whether an edge is in the
63 ///spanning tree or not.
64 ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
65 ///By default it is a BoolEdgeMap.
66 typedef typename UGraph::template UEdgeMap<bool> TreeMap;
67 ///Instantiates a TreeMap.
69 ///This function instantiates a \ref TreeMap.
70 ///\param _graph is the graph, to which
71 ///we would like to define the \ref TreeMap
72 static TreeMap *createTreeMap(const GR &_graph){
73 return new TreeMap(_graph);
77 ///%FredmanTarjan algorithm class to find a minimum spanning tree.
81 ///This class provides an efficient implementation of %FredmanTarjan
82 ///algorithm whitch is sometimes a bit quicker than the Prim
83 ///algorithm on larger graphs. Due to the structure of the
84 ///algorithm, it has less controll functions than Prim.
86 /// The running time is \f$ O(e\beta(e,n)) \f$ where
87 /// \f$ \beta(e,n) = \min\{ i | \log^{i}(n) \le e/n\} \f$ and
88 /// \f$ \log^{i+1}(n)=\log(\log^{i}(n)) \f$
90 ///The edge costs are passed to the algorithm using a \ref
91 ///concepts::ReadMap "ReadMap", so it is easy to change it to any
94 ///The type of the cost is determined by the \ref
95 ///concepts::ReadMap::Value "Value" of the cost map.
97 ///\param GR The graph type the algorithm runs on. The default value
98 ///is \ref ListUGraph. The value of GR is not used directly by
99 ///FredmanTarjan, it is only passed to \ref
100 ///FredmanTarjanDefaultTraits.
102 ///\param CM This read-only UEdgeMap determines the costs of the
103 ///edges. It is read once for each edge, so the map may involve in
104 ///relatively time consuming process to compute the edge cost if it
105 ///is necessary. The default map type is \ref
106 ///concepts::UGraph::UEdgeMap "UGraph::UEdgeMap<int>". The value of
107 ///CM is not used directly by FredmanTarjan, it is only passed to
108 ///\ref FredmanTarjanDefaultTraits.
110 ///\param TR Traits class to set various data types used by the
111 ///algorithm. The default traits class is \ref
112 ///FredmanTarjanDefaultTraits "FredmanTarjanDefaultTraits<GR,CM>".
113 ///See \ref FredmanTarjanDefaultTraits for the documentation of a
114 ///FredmanTarjan traits class.
116 ///\author Balazs Attila Mihaly
119 template <typename GR,
123 template <typename GR=ListUGraph,
124 typename CM=typename GR::template UEdgeMap<int>,
125 typename TR=FredmanTarjanDefaultTraits<GR,CM> >
127 class FredmanTarjan {
129 ///\brief \ref Exception for uninitialized parameters.
131 ///This error represents problems in the initialization
132 ///of the parameters of the algorithms.
133 class UninitializedParameter : public lemon::UninitializedParameter {
135 virtual const char* what() const throw() {
136 return "lemon::FredmanTarjan::UninitializedParameter";
142 ///The type of the underlying graph.
143 typedef typename TR::UGraph UGraph;
145 typedef typename UGraph::Node Node;
147 typedef typename UGraph::NodeIt NodeIt;
149 typedef typename UGraph::UEdge UEdge;
151 typedef typename UGraph::UEdgeIt UEdgeIt;
153 typedef typename UGraph::IncEdgeIt IncEdgeIt;
155 ///The type of the cost of the edges.
156 typedef typename TR::CostMap::Value Value;
157 ///The type of the map that stores the edge costs.
158 typedef typename TR::CostMap CostMap;
159 ///Edges of the spanning tree.
160 typedef typename TR::TreeMap TreeMap;
162 ///Pointer to the underlying graph.
164 ///Pointer to the cost map
166 ///Pointer to the map of tree edges.
168 ///Indicates if \ref _tree is locally allocated (\c true) or not.
171 ///Creates the maps if necessary.
176 _tree=Traits::createTreeMap(*graph);
182 typedef FredmanTarjan Create;
184 ///\name Named template parameters
189 struct DefTreeMapTraits : public Traits {
191 static TreeMap *createTreeMap(const UGraph &) {
192 throw UninitializedParameter();
195 ///\brief \ref named-templ-param "Named parameter" for setting TreeMap
197 ///\ref named-templ-param "Named parameter" for setting TreeMap
201 : public FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > {
202 typedef FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > Create;
214 template<class SrcGraph,class OrigMap,class Heap,class HeapCrossRef,
215 class ProcessedMap,class PredMap>
216 void processNextTree(const SrcGraph& graph,const OrigMap& orig,
217 Heap &heap, HeapCrossRef& crossref,
218 ProcessedMap& processed,PredMap& pred,
219 int& tree_counter,const int limit){
220 std::vector<typename SrcGraph::Node> tree_nodes;
221 int tree_index=tree_counter;
223 while(!heap.empty() && !stop){
224 typename SrcGraph::Node v=heap.top();
226 if(processed[v]!=-1){
227 heap.state(v,Heap::PRE_HEAP);
228 tree_index=processed[v];
229 _tree->set(orig[pred[v]],true);
233 tree_nodes.push_back(v);
234 for(typename SrcGraph::IncEdgeIt e(graph,v);e!=INVALID;++e){
235 typename SrcGraph::Node w=graph.oppositeNode(v,e);
236 switch(heap.state(w)){
238 if(heap.size()>=limit){
242 heap.push(w,(*cost)[orig[e]]);
247 if ((*cost)[orig[e]]<heap[w]){
248 heap.decrease(w,(*cost)[orig[e]]);
252 case Heap::POST_HEAP:
257 for(int i=1;i<(int)tree_nodes.size();++i){
258 _tree->set(orig[pred[tree_nodes[i]]],true);
259 processed.set(tree_nodes[i],tree_index);
260 crossref[tree_nodes[i]] = Heap::PRE_HEAP;
262 processed.set(tree_nodes[0],tree_index);
263 crossref[tree_nodes[0]] = Heap::PRE_HEAP;
264 while (!heap.empty()) {
265 typename SrcGraph::Node v=heap.top();
267 crossref[v] = Heap::PRE_HEAP;
270 if(!stop)++tree_counter;
273 template<class SrcGraph,class OrigMap,class ProcessedMap>
274 void createTrees(const SrcGraph& graph, const OrigMap& orig,
275 ProcessedMap& processed,
276 int edgenum,int& tree_counter){
277 typedef typename SrcGraph::Node Node;
278 typedef typename SrcGraph::UEdge UEdge;
279 typedef typename SrcGraph::NodeIt NodeIt;
280 typedef typename SrcGraph::template NodeMap<int> HeapCrossRef;
281 typedef typename SrcGraph::template NodeMap<UEdge> PredMap;
282 HeapCrossRef crossref(graph,-1);
283 FibHeap<Value,HeapCrossRef> heap(crossref);
284 PredMap pred(graph,INVALID);
285 int rate=2*edgenum/countNodes(graph);
286 int limit=(rate>std::numeric_limits<int>::digits)?
287 std::numeric_limits<int>::max() : (1<<rate);
288 for(NodeIt i(graph);i!=INVALID;++i){
289 if(processed[i]==-1){
290 heap.push(i, Value());
291 processNextTree(graph,orig,heap,crossref,
292 processed,pred,tree_counter,limit);
297 template<class SrcGraph,class DestGraph,class SrcOrigMap,
298 class DestOrigMap,class ProcessedMap>
299 void collect(const SrcGraph& srcgraph,const SrcOrigMap& srcorig,
300 DestGraph& destgraph,DestOrigMap& destorig,
301 const ProcessedMap& processed,const int tree_counter){
302 typedef typename SrcGraph::Node Node;
303 typedef typename DestGraph::Node DNode;
304 typedef typename SrcGraph::UEdge UEdge;
305 typedef typename DestGraph::UEdge DUEdge;
306 typedef typename SrcGraph::Edge Edge;
307 typedef typename SrcGraph::EdgeIt EdgeIt;
308 std::vector<Edge> edges;
309 std::vector<DNode> nodes(tree_counter, INVALID);
310 for(EdgeIt i(srcgraph);i!=INVALID;++i){
311 if(processed[srcgraph.source(i)]<processed[srcgraph.target(i)]){
313 if(nodes[processed[srcgraph.source(i)]]==INVALID) {
314 nodes[processed[srcgraph.source(i)]]=destgraph.addNode();
316 if(nodes[processed[srcgraph.target(i)]]==INVALID) {
317 nodes[processed[srcgraph.target(i)]]=destgraph.addNode();
322 radixSort(edges.begin(),edges.end(),
323 mapFunctor(composeMap(processed,sourceMap(srcgraph))));
324 counterSort(edges.begin(),edges.end(),
325 mapFunctor(composeMap(processed,targetMap(srcgraph))));
326 for(int i=0;i!=(int)edges.size();++i){
327 int srcproc=processed[srcgraph.source(edges[i])];
328 int trgproc=processed[srcgraph.target(edges[i])];
329 Value minval=(*cost)[srcorig[edges[i]]];
330 UEdge minpos=edges[i];
331 while (i+1!=(int)edges.size() &&
332 srcproc==processed[srcgraph.source(edges[i+1])] &&
333 trgproc==processed[srcgraph.target(edges[i+1])]) {
334 if (minval>(*cost)[srcorig[edges[i+1]]]) {
335 minval=(*cost)[srcorig[edges[i+1]]];
340 destorig[destgraph.addEdge(nodes[srcproc],nodes[trgproc])]=
345 template<class SrcGraph,class OrigMap>
346 void phase(const SrcGraph& graph,const OrigMap& orig,int edgenum){
347 int tree_counter = 0;
348 typename SrcGraph::template NodeMap<int> processed(graph,-1);
349 SmartUGraph destgraph;
350 SmartUGraph::UEdgeMap<typename OrigMap::Value> destorig(destgraph);
351 createTrees(graph,orig,processed,edgenum,tree_counter);
352 collect(graph,orig,destgraph,destorig,processed,tree_counter);
353 if (countNodes(destgraph)>1) {
354 phase(destgraph,destorig,edgenum);
362 ///\param _graph the graph the algorithm will run on.
363 ///\param _cost the cost map used by the algorithm.
364 FredmanTarjan(const UGraph& _graph, const CostMap& _cost) :
365 graph(&_graph), cost(&_cost),
366 _tree(0), local_tree(false)
368 checkConcept<concepts::UGraph, UGraph>();
373 if(local_tree) delete _tree;
376 ///Sets the cost map.
378 ///Sets the cost map.
379 ///\return <tt> (*this) </tt>
380 FredmanTarjan &costMap(const CostMap &m){
385 ///Sets the map storing the tree edges.
387 ///Sets the map storing the tree edges.
388 ///If you don't use this function before calling \ref run(),
389 ///it will allocate one. The destuctor deallocates this
390 ///automatically allocated map, of course.
391 ///By default this is a BoolEdgeMap.
392 ///\return <tt> (*this) </tt>
393 FredmanTarjan &treeMap(TreeMap &m){
403 ///\name Execution control
404 ///The simplest way to execute the algorithm is to use
405 ///one of the member functions called \c run(...).
409 ///Initializes the internal data structures.
411 ///Initializes the internal data structures.
415 for(typename Graph::UEdgeIt i(*graph);i!=INVALID;++i){
420 ///Executes the algorithm.
422 ///Executes the algorithm.
424 ///\pre init() must be called and at least one node should be added
425 ///with addSource() before using this function.
427 ///This method runs the %FredmanTarjan algorithm from the node(s)
428 ///in order to compute the
429 ///minimum spanning tree.
431 phase(*graph,identityMap<UEdge>(),countEdges(*graph));
434 ///Runs %FredmanTarjan algorithm.
436 ///This method runs the %FredmanTarjan algorithm
437 ///in order to compute the minimum spanning forest.
439 ///\note ft.run() is just a shortcut of the following code.
451 ///\name Query Functions
452 ///The result of the %FredmanTarjan algorithm can be obtained using these
454 ///Before the use of these functions,
455 ///either run() or start() must be called.
459 ///Returns a reference to the tree edges map.
461 ///Returns a reference to the TreeEdgeMap of the edges of the
462 ///minimum spanning tree. The value of the map is \c true only if the
463 ///edge is in the minimum spanning tree.
465 ///\pre \ref run() or \ref start() must be called before using this
467 const TreeMap &treeMap() const { return *_tree;}
469 ///Sets the tree edges map.
471 ///Sets the TreeMap of the edges of the minimum spanning tree.
472 ///The map values belonging to the edges of the minimum
473 ///spanning tree are set to \c tree_edge_value or \c true by default
474 ///while the edge values not belonging to the minimum spanning tree are
476 ///\c tree_default_value or \c false by default.
478 ///\pre \ref run() or \ref start() must be called before using this
481 template<class TreeMap>
484 const typename TreeMap::Value& tree_edge_value=true,
485 const typename TreeMap::Value& tree_default_value=false) const {
486 for(typename UGraph::UEdgeIt i(*graph);i!=INVALID;++i){
487 (*_tree)[i]?tree.set(i,tree_edge_value):tree.set(i,tree_default_value);
491 ///\brief Checks if an edge is in the spanning tree or not.
493 ///Checks if an edge is in the spanning tree or not.
494 ///\param e is the edge that will be checked
495 ///\return \c true if e is in the spanning tree, \c false otherwise
502 /// \ingroup spantree
504 /// \brief Function type interface for FredmanTarjan algorithm.
506 /// Function type interface for FredmanTarjan algorithm.
507 /// \param graph the UGraph that the algorithm runs on
508 /// \param cost the CostMap of the edges
509 /// \retval tree the EdgeMap that contains whether an edge is in the
510 /// spanning tree or not
513 template<class Graph,class CostMap,class TreeMap>
514 void fredmanTarjan(const Graph& graph, const CostMap& cost,TreeMap& tree){
515 typename FredmanTarjan<Graph,CostMap>::template DefTreeMap<TreeMap>::
516 Create ft(graph,cost);
521 } //END OF NAMESPACE LEMON