deba@1912
|
1 |
/* -*- C++ -*-
|
deba@1912
|
2 |
* lemon/fredman_tarjan.h - Part of LEMON, a generic C++ optimization library
|
deba@1912
|
3 |
*
|
deba@1912
|
4 |
* Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
deba@1912
|
5 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
deba@1912
|
6 |
*
|
deba@1912
|
7 |
* Permission to use, modify and distribute this software is granted
|
deba@1912
|
8 |
* provided that this copyright notice appears in all copies. For
|
deba@1912
|
9 |
* precise terms see the accompanying LICENSE file.
|
deba@1912
|
10 |
*
|
deba@1912
|
11 |
* This software is provided "AS IS" with no warranty of any kind,
|
deba@1912
|
12 |
* express or implied, and with no claim as to its suitability for any
|
deba@1912
|
13 |
* purpose.
|
deba@1912
|
14 |
*
|
deba@1912
|
15 |
*/
|
deba@1912
|
16 |
|
deba@1912
|
17 |
#ifndef LEMON_FREDMAN_TARJAN_H
|
deba@1912
|
18 |
#define LEMON_FREDMAN_TARJAN_H
|
deba@1912
|
19 |
|
deba@1912
|
20 |
///\ingroup spantree
|
deba@1912
|
21 |
///\file
|
deba@1912
|
22 |
///\brief FredmanTarjan algorithm to compute minimum spanning forest.
|
deba@1912
|
23 |
|
deba@1912
|
24 |
#include <limits>
|
deba@1912
|
25 |
#include <vector>
|
deba@1912
|
26 |
|
deba@1912
|
27 |
#include <lemon/list_graph.h>
|
deba@1912
|
28 |
#include <lemon/smart_graph.h>
|
deba@1912
|
29 |
#include <lemon/fib_heap.h>
|
deba@1912
|
30 |
#include <lemon/radix_sort.h>
|
deba@1912
|
31 |
#include <lemon/invalid.h>
|
deba@1912
|
32 |
#include <lemon/error.h>
|
deba@1912
|
33 |
#include <lemon/maps.h>
|
deba@1912
|
34 |
#include <lemon/traits.h>
|
deba@1912
|
35 |
#include <lemon/graph_utils.h>
|
deba@1912
|
36 |
|
deba@1912
|
37 |
#include <lemon/concept/ugraph.h>
|
deba@1912
|
38 |
|
deba@1912
|
39 |
namespace lemon {
|
deba@1912
|
40 |
|
deba@1912
|
41 |
///Default traits class of FredmanTarjan class.
|
deba@1912
|
42 |
|
deba@1912
|
43 |
///Default traits class of FredmanTarjan class.
|
deba@1912
|
44 |
///\param GR Graph type.
|
deba@1912
|
45 |
///\param LM Type of cost map.
|
deba@1912
|
46 |
template<class GR, class LM>
|
deba@1912
|
47 |
struct FredmanTarjanDefaultTraits{
|
deba@1912
|
48 |
///The graph type the algorithm runs on.
|
deba@1912
|
49 |
typedef GR UGraph;
|
deba@1912
|
50 |
///The type of the map that stores the edge costs.
|
deba@1912
|
51 |
|
deba@1912
|
52 |
///The type of the map that stores the edge costs.
|
deba@1912
|
53 |
///It must meet the \ref concept::ReadMap "ReadMap" concept.
|
deba@1912
|
54 |
typedef LM CostMap;
|
deba@1912
|
55 |
//The type of the cost of the edges.
|
deba@1912
|
56 |
typedef typename LM::Value Value;
|
deba@1912
|
57 |
///The type of the map that stores whether an edge is in the
|
deba@1912
|
58 |
///spanning tree or not.
|
deba@1912
|
59 |
|
deba@1912
|
60 |
///The type of the map that stores whether an edge is in the
|
deba@1912
|
61 |
///spanning tree or not.
|
deba@1912
|
62 |
///It must meet the \ref concept::ReadWriteMap "ReadWriteMap" concept.
|
deba@1912
|
63 |
///By default it is a BoolEdgeMap.
|
deba@1912
|
64 |
typedef typename UGraph::template UEdgeMap<bool> TreeMap;
|
deba@1912
|
65 |
///Instantiates a TreeMap.
|
deba@1912
|
66 |
|
deba@1912
|
67 |
///This function instantiates a \ref TreeMap.
|
deba@1912
|
68 |
///\param g is the graph, to which
|
deba@1912
|
69 |
///we would like to define the \ref TreeMap
|
deba@1912
|
70 |
static TreeMap *createTreeMap(const GR &_graph){
|
deba@1912
|
71 |
return new TreeMap(_graph);
|
deba@1912
|
72 |
}
|
deba@1912
|
73 |
};
|
deba@1912
|
74 |
|
deba@1912
|
75 |
///%FredmanTarjan algorithm class to find a minimum spanning tree.
|
deba@1912
|
76 |
|
deba@1912
|
77 |
/// \ingroup spantree
|
deba@1912
|
78 |
///This class provides an efficient implementation of %FredmanTarjan algorithm
|
deba@1912
|
79 |
///whitch is sometimes a bit quicker than the Prim algorithm on larger graphs.
|
deba@1912
|
80 |
///Due to the structure of the algorithm, it has less controll functions than
|
deba@1912
|
81 |
///Prim.
|
deba@1912
|
82 |
///
|
deba@1912
|
83 |
///The running time is O(e*B(e,n)) where e is the number of edges, n is the
|
deba@1912
|
84 |
///number of nodes in the graph and B(e,n) is min { i | log^(i) n <= e/n}
|
deba@1912
|
85 |
///( log^(i+1) n = log(log^(i)) n )
|
deba@1912
|
86 |
///
|
deba@1912
|
87 |
///The edge costs are passed to the algorithm using a
|
deba@1912
|
88 |
///\ref concept::ReadMap "ReadMap",
|
deba@1912
|
89 |
///so it is easy to change it to any kind of cost.
|
deba@1912
|
90 |
///
|
deba@1912
|
91 |
///The type of the cost is determined by the
|
deba@1912
|
92 |
///\ref concept::ReadMap::Value "Value" of the cost map.
|
deba@1912
|
93 |
///
|
deba@1912
|
94 |
///\param GR The graph type the algorithm runs on. The default value
|
deba@1912
|
95 |
///is \ref ListUGraph. The value of GR is not used directly by
|
deba@1912
|
96 |
///FredmanTarjan, it is only passed to \ref FredmanTarjanDefaultTraits.
|
deba@1912
|
97 |
///
|
deba@1912
|
98 |
///\param LM This read-only UEdgeMap determines the costs of the
|
deba@1912
|
99 |
///edges. It is read once for each edge, so the map may involve in
|
deba@1912
|
100 |
///relatively time consuming process to compute the edge cost if
|
deba@1912
|
101 |
///it is necessary. The default map type is \ref
|
deba@1912
|
102 |
///concept::UGraph::UEdgeMap "UGraph::UEdgeMap<int>". The value
|
deba@1912
|
103 |
///of LM is not used directly by FredmanTarjan, it is only passed to \ref
|
deba@1912
|
104 |
///FredmanTarjanDefaultTraits.
|
deba@1912
|
105 |
///
|
deba@1912
|
106 |
///\param TR Traits class to set
|
deba@1912
|
107 |
///various data types used by the algorithm. The default traits
|
deba@1912
|
108 |
///class is \ref FredmanTarjanDefaultTraits
|
deba@1912
|
109 |
///"FredmanTarjanDefaultTraits<GR,LM>". See \ref
|
deba@1912
|
110 |
///FredmanTarjanDefaultTraits for the documentation of a FredmanTarjan traits
|
deba@1912
|
111 |
///class.
|
deba@1912
|
112 |
///
|
deba@1912
|
113 |
///\author Balazs Attila Mihaly
|
deba@1912
|
114 |
|
deba@1912
|
115 |
#ifdef DOXYGEN
|
deba@1912
|
116 |
template <typename GR,
|
deba@1912
|
117 |
typename LM,
|
deba@1912
|
118 |
typename TR>
|
deba@1912
|
119 |
#else
|
deba@1912
|
120 |
template <typename GR=ListUGraph,
|
deba@1912
|
121 |
typename LM=typename GR::template UEdgeMap<int>,
|
deba@1912
|
122 |
typename TR=FredmanTarjanDefaultTraits<GR,LM> >
|
deba@1912
|
123 |
#endif
|
deba@1912
|
124 |
class FredmanTarjan {
|
deba@1912
|
125 |
public:
|
deba@1912
|
126 |
/**
|
deba@1912
|
127 |
* \brief \ref Exception for uninitialized parameters.
|
deba@1912
|
128 |
*
|
deba@1912
|
129 |
* This error represents problems in the initialization
|
deba@1912
|
130 |
* of the parameters of the algorithms.
|
deba@1912
|
131 |
*/
|
deba@1912
|
132 |
class UninitializedParameter : public lemon::UninitializedParameter {
|
deba@1912
|
133 |
public:
|
deba@1912
|
134 |
virtual const char* exceptionName() const {
|
deba@1912
|
135 |
return "lemon::FredmanTarjan::UninitializedParameter";
|
deba@1912
|
136 |
}
|
deba@1912
|
137 |
};
|
deba@1912
|
138 |
|
deba@1912
|
139 |
typedef GR Graph;
|
deba@1912
|
140 |
typedef TR Traits;
|
deba@1912
|
141 |
///The type of the underlying graph.
|
deba@1912
|
142 |
typedef typename TR::UGraph UGraph;
|
deba@1912
|
143 |
///\e
|
deba@1912
|
144 |
typedef typename UGraph::Node Node;
|
deba@1912
|
145 |
///\e
|
deba@1912
|
146 |
typedef typename UGraph::NodeIt NodeIt;
|
deba@1912
|
147 |
///\e
|
deba@1912
|
148 |
typedef typename UGraph::UEdge UEdge;
|
deba@1912
|
149 |
///\e
|
deba@1912
|
150 |
typedef typename UGraph::UEdgeIt UEdgeIt;
|
deba@1912
|
151 |
///\e
|
deba@1912
|
152 |
typedef typename UGraph::IncEdgeIt IncEdgeIt;
|
deba@1912
|
153 |
|
deba@1912
|
154 |
///The type of the cost of the edges.
|
deba@1912
|
155 |
typedef typename TR::CostMap::Value Value;
|
deba@1912
|
156 |
///The type of the map that stores the edge costs.
|
deba@1912
|
157 |
typedef typename TR::CostMap CostMap;
|
deba@1912
|
158 |
///Edges of the spanning tree.
|
deba@1912
|
159 |
typedef typename TR::TreeMap TreeMap;
|
deba@1912
|
160 |
private:
|
deba@1912
|
161 |
///Pointer to the underlying graph.
|
deba@1912
|
162 |
const UGraph *graph;
|
deba@1912
|
163 |
///Pointer to the cost map
|
deba@1912
|
164 |
const CostMap *cost;
|
deba@1912
|
165 |
///Pointer to the map of tree edges.
|
deba@1912
|
166 |
TreeMap *_tree;
|
deba@1912
|
167 |
///Indicates if \ref _tree is locally allocated (\c true) or not.
|
deba@1912
|
168 |
bool local_tree;
|
deba@1912
|
169 |
|
deba@1912
|
170 |
///Creates the maps if necessary.
|
deba@1912
|
171 |
|
deba@1912
|
172 |
void create_maps(){
|
deba@1912
|
173 |
if(!_tree){
|
deba@1912
|
174 |
local_tree=true;
|
deba@1912
|
175 |
_tree=Traits::createTreeMap(*graph);
|
deba@1912
|
176 |
}
|
deba@1912
|
177 |
}
|
deba@1912
|
178 |
|
deba@1912
|
179 |
public :
|
deba@1912
|
180 |
|
deba@1912
|
181 |
typedef FredmanTarjan Create;
|
deba@1912
|
182 |
|
deba@1912
|
183 |
///\name Named template parameters
|
deba@1912
|
184 |
|
deba@1912
|
185 |
///@{
|
deba@1912
|
186 |
|
deba@1912
|
187 |
template <class TM>
|
deba@1912
|
188 |
struct DefTreeMapTraits : public Traits {
|
deba@1912
|
189 |
typedef TM TreeMap;
|
deba@1912
|
190 |
static TreeMap *createTreeMap(const UGraph &) {
|
deba@1912
|
191 |
throw UninitializedParameter();
|
deba@1912
|
192 |
}
|
deba@1912
|
193 |
};
|
deba@1912
|
194 |
///\ref named-templ-param "Named parameter" for setting TreeMap
|
deba@1912
|
195 |
|
deba@1912
|
196 |
///\ref named-templ-param "Named parameter" for setting TreeMap
|
deba@1912
|
197 |
///
|
deba@1912
|
198 |
template <class TM>
|
deba@1912
|
199 |
struct DefTreeMap
|
deba@1912
|
200 |
: public FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > {
|
deba@1912
|
201 |
typedef FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > Create;
|
deba@1912
|
202 |
};
|
deba@1912
|
203 |
|
deba@1912
|
204 |
///@}
|
deba@1912
|
205 |
|
deba@1912
|
206 |
|
deba@1912
|
207 |
protected:
|
deba@1912
|
208 |
|
deba@1912
|
209 |
FredmanTarjan() {}
|
deba@1912
|
210 |
|
deba@1912
|
211 |
private:
|
deba@1912
|
212 |
|
deba@1912
|
213 |
template<class SrcGraph,class OrigMap,class Heap,class ProcessedMap,class PredMap>
|
deba@1912
|
214 |
void processNextTree(const SrcGraph& graph,const OrigMap& orig,Heap &heap,
|
deba@1912
|
215 |
ProcessedMap& processed,PredMap& pred,int& tree_counter,const int limit){
|
deba@1912
|
216 |
std::vector<typename SrcGraph::Node> tree_nodes;
|
deba@1912
|
217 |
int tree_index=tree_counter;
|
deba@1912
|
218 |
bool stop=false;
|
deba@1912
|
219 |
while(!heap.empty() && !stop){
|
deba@1912
|
220 |
typename SrcGraph::Node v=heap.top();
|
deba@1912
|
221 |
heap.pop();
|
deba@1912
|
222 |
if(processed[v]!=-1){
|
deba@1912
|
223 |
heap.state(v,Heap::PRE_HEAP);
|
deba@1912
|
224 |
tree_index=processed[v];
|
deba@1912
|
225 |
_tree->set(orig[pred[v]],true);
|
deba@1912
|
226 |
stop=true;
|
deba@1912
|
227 |
break;
|
deba@1912
|
228 |
}
|
deba@1912
|
229 |
tree_nodes.push_back(v);
|
deba@1912
|
230 |
for(typename SrcGraph::IncEdgeIt e(graph,v);e!=INVALID;++e){
|
deba@1912
|
231 |
typename SrcGraph::Node w=graph.oppositeNode(v,e);
|
deba@1912
|
232 |
switch(heap.state(w)){
|
deba@1912
|
233 |
case Heap::PRE_HEAP:
|
deba@1912
|
234 |
if(heap.size()>=limit){
|
deba@1912
|
235 |
stop=true;
|
deba@1912
|
236 |
}
|
deba@1912
|
237 |
else{
|
deba@1912
|
238 |
heap.push(w,(*cost)[orig[e]]);
|
deba@1912
|
239 |
pred.set(w,e);
|
deba@1912
|
240 |
}
|
deba@1912
|
241 |
break;
|
deba@1912
|
242 |
case Heap::IN_HEAP:
|
deba@1912
|
243 |
if ((*cost)[orig[e]]<heap[w]){
|
deba@1912
|
244 |
heap.decrease(w,(*cost)[orig[e]]);
|
deba@1912
|
245 |
pred.set(w,e);
|
deba@1912
|
246 |
}
|
deba@1912
|
247 |
break;
|
deba@1912
|
248 |
case Heap::POST_HEAP:
|
deba@1912
|
249 |
break;
|
deba@1912
|
250 |
}
|
deba@1912
|
251 |
}
|
deba@1912
|
252 |
}
|
deba@1912
|
253 |
for(int i=1;i<(int)tree_nodes.size();++i){
|
deba@1912
|
254 |
_tree->set(orig[pred[tree_nodes[i]]],true);
|
deba@1912
|
255 |
processed.set(tree_nodes[i],tree_index);
|
deba@1912
|
256 |
heap.state(tree_nodes[i], Heap::PRE_HEAP);
|
deba@1912
|
257 |
}
|
deba@1912
|
258 |
processed.set(tree_nodes[0],tree_index);
|
deba@1912
|
259 |
heap.state(tree_nodes[0],Heap::PRE_HEAP);
|
deba@1912
|
260 |
while (!heap.empty()) {
|
deba@1912
|
261 |
typename SrcGraph::Node v=heap.top();
|
deba@1912
|
262 |
heap.pop();
|
deba@1912
|
263 |
heap.state(v,Heap::PRE_HEAP);
|
deba@1912
|
264 |
}
|
deba@1912
|
265 |
if(!stop)++tree_counter;
|
deba@1912
|
266 |
}
|
deba@1912
|
267 |
|
deba@1912
|
268 |
template<class SrcGraph,class OrigMap,class ProcessedMap>
|
deba@1912
|
269 |
void createTrees(const SrcGraph& graph,const OrigMap& orig, ProcessedMap& processed,
|
deba@1912
|
270 |
int edgenum,int& tree_counter){
|
deba@1912
|
271 |
typedef typename SrcGraph::Node Node;
|
deba@1912
|
272 |
typedef typename SrcGraph::UEdge UEdge;
|
deba@1912
|
273 |
typedef typename SrcGraph::NodeIt NodeIt;
|
deba@1912
|
274 |
typedef typename SrcGraph::template NodeMap<int> HeapCrossRef;
|
deba@1912
|
275 |
typedef typename SrcGraph::template NodeMap<UEdge> PredMap;
|
deba@1912
|
276 |
HeapCrossRef crossref(graph,-1);
|
deba@1912
|
277 |
FibHeap<Node,Value,HeapCrossRef> heap(crossref);
|
deba@1912
|
278 |
PredMap pred(graph,INVALID);
|
deba@1912
|
279 |
int rate=2*edgenum/countNodes(graph);
|
deba@1912
|
280 |
int limit=(rate>std::numeric_limits<int>::digits)?std::numeric_limits<int>::max():(1<<rate);
|
deba@1912
|
281 |
for(NodeIt i(graph);i!=INVALID;++i){
|
deba@1912
|
282 |
if(processed[i]==-1){
|
deba@1912
|
283 |
heap.push(i, Value());
|
deba@1912
|
284 |
processNextTree(graph,orig,heap,processed,pred,tree_counter,limit);
|
deba@1912
|
285 |
}
|
deba@1912
|
286 |
}
|
deba@1912
|
287 |
}
|
deba@1912
|
288 |
|
deba@1912
|
289 |
template<class SrcGraph,class DestGraph,class SrcOrigMap,class DestOrigMap,class ProcessedMap>
|
deba@1912
|
290 |
void collect(const SrcGraph& srcgraph,const SrcOrigMap& srcorig,DestGraph& destgraph,
|
deba@1912
|
291 |
DestOrigMap& destorig,const ProcessedMap& processed,const int tree_counter){
|
deba@1912
|
292 |
typedef typename SrcGraph::Node Node;
|
deba@1912
|
293 |
typedef typename DestGraph::Node DNode;
|
deba@1912
|
294 |
typedef typename SrcGraph::UEdge UEdge;
|
deba@1912
|
295 |
typedef typename DestGraph::UEdge DUEdge;
|
deba@1912
|
296 |
typedef typename SrcGraph::Edge Edge;
|
deba@1912
|
297 |
typedef typename SrcGraph::EdgeIt EdgeIt;
|
deba@1912
|
298 |
std::vector<Edge> edges;
|
deba@1912
|
299 |
std::vector<DNode> nodes(tree_counter, INVALID);
|
deba@1912
|
300 |
for(EdgeIt i(srcgraph);i!=INVALID;++i){
|
deba@1912
|
301 |
if(processed[srcgraph.source(i)]<processed[srcgraph.target(i)]){
|
deba@1912
|
302 |
edges.push_back(i);
|
deba@1912
|
303 |
if(nodes[processed[srcgraph.source(i)]]==INVALID) {
|
deba@1912
|
304 |
nodes[processed[srcgraph.source(i)]]=destgraph.addNode();
|
deba@1912
|
305 |
}
|
deba@1912
|
306 |
if(nodes[processed[srcgraph.target(i)]]==INVALID) {
|
deba@1912
|
307 |
nodes[processed[srcgraph.target(i)]]=destgraph.addNode();
|
deba@1912
|
308 |
}
|
deba@1912
|
309 |
}
|
deba@1912
|
310 |
}
|
deba@1912
|
311 |
|
deba@1912
|
312 |
radixSort(edges.begin(),edges.end(),mapFunctor(composeMap(processed,sourceMap(srcgraph))));
|
deba@1912
|
313 |
counterSort(edges.begin(),edges.end(),mapFunctor(composeMap(processed,targetMap(srcgraph))));
|
deba@1912
|
314 |
for(int i=0;i!=(int)edges.size();++i){
|
deba@1912
|
315 |
int srcproc=processed[srcgraph.source(edges[i])];
|
deba@1912
|
316 |
int trgproc=processed[srcgraph.target(edges[i])];
|
deba@1912
|
317 |
Value minval=(*cost)[srcorig[edges[i]]];
|
deba@1912
|
318 |
UEdge minpos=edges[i];
|
deba@1912
|
319 |
while (i+1!=(int)edges.size() && srcproc==processed[srcgraph.source(edges[i+1])] &&
|
deba@1912
|
320 |
trgproc==processed[srcgraph.target(edges[i+1])]) {
|
deba@1912
|
321 |
if (minval>(*cost)[srcorig[edges[i+1]]]) {
|
deba@1912
|
322 |
minval=(*cost)[srcorig[edges[i+1]]];
|
deba@1912
|
323 |
minpos=edges[i+1];
|
deba@1912
|
324 |
}
|
deba@1912
|
325 |
++i;
|
deba@1912
|
326 |
}
|
deba@1912
|
327 |
destorig[destgraph.addEdge(nodes[srcproc],nodes[trgproc])]=srcorig[minpos];
|
deba@1912
|
328 |
}
|
deba@1912
|
329 |
}
|
deba@1912
|
330 |
|
deba@1912
|
331 |
template<class SrcGraph,class OrigMap>
|
deba@1912
|
332 |
void phase(const SrcGraph& graph,const OrigMap& orig,int edgenum){
|
deba@1912
|
333 |
int tree_counter = 0;
|
deba@1912
|
334 |
typename SrcGraph::template NodeMap<int> processed(graph,-1);
|
deba@1912
|
335 |
SmartUGraph destgraph;
|
deba@1912
|
336 |
SmartUGraph::UEdgeMap<typename OrigMap::Value> destorig(destgraph);
|
deba@1912
|
337 |
createTrees(graph,orig,processed,edgenum,tree_counter);
|
deba@1912
|
338 |
collect(graph,orig,destgraph,destorig,processed,tree_counter);
|
deba@1912
|
339 |
if (countNodes(destgraph)>1) {
|
deba@1912
|
340 |
phase(destgraph,destorig,edgenum);
|
deba@1912
|
341 |
}
|
deba@1912
|
342 |
}
|
deba@1912
|
343 |
|
deba@1912
|
344 |
public:
|
deba@1912
|
345 |
|
deba@1912
|
346 |
///Constructor.
|
deba@1912
|
347 |
|
deba@1912
|
348 |
///\param _graph the graph the algorithm will run on.
|
deba@1912
|
349 |
///\param _cost the cost map used by the algorithm.
|
deba@1912
|
350 |
FredmanTarjan(const UGraph& _graph, const CostMap& _cost) :
|
deba@1912
|
351 |
graph(&_graph), cost(&_cost),
|
deba@1912
|
352 |
_tree(0), local_tree(false)
|
deba@1912
|
353 |
{
|
deba@1912
|
354 |
checkConcept<concept::UGraph, UGraph>();
|
deba@1912
|
355 |
}
|
deba@1912
|
356 |
|
deba@1912
|
357 |
///Destructor.
|
deba@1912
|
358 |
~FredmanTarjan(){
|
deba@1912
|
359 |
if(local_tree) delete _tree;
|
deba@1912
|
360 |
}
|
deba@1912
|
361 |
|
deba@1912
|
362 |
///Sets the cost map.
|
deba@1912
|
363 |
|
deba@1912
|
364 |
///Sets the cost map.
|
deba@1912
|
365 |
///\return <tt> (*this) </tt>
|
deba@1912
|
366 |
FredmanTarjan &costMap(const CostMap &m){
|
deba@1912
|
367 |
cost = &m;
|
deba@1912
|
368 |
return *this;
|
deba@1912
|
369 |
}
|
deba@1912
|
370 |
|
deba@1912
|
371 |
///Sets the map storing the tree edges.
|
deba@1912
|
372 |
|
deba@1912
|
373 |
///Sets the map storing the tree edges.
|
deba@1912
|
374 |
///If you don't use this function before calling \ref run(),
|
deba@1912
|
375 |
///it will allocate one. The destuctor deallocates this
|
deba@1912
|
376 |
///automatically allocated map, of course.
|
deba@1912
|
377 |
///By default this is a BoolEdgeMap.
|
deba@1912
|
378 |
///\return <tt> (*this) </tt>
|
deba@1912
|
379 |
FredmanTarjan &treeMap(TreeMap &m){
|
deba@1912
|
380 |
if(local_tree) {
|
deba@1912
|
381 |
delete _tree;
|
deba@1912
|
382 |
local_tree=false;
|
deba@1912
|
383 |
}
|
deba@1912
|
384 |
_tree = &m;
|
deba@1912
|
385 |
return *this;
|
deba@1912
|
386 |
}
|
deba@1912
|
387 |
|
deba@1912
|
388 |
public:
|
deba@1912
|
389 |
///\name Execution control
|
deba@1912
|
390 |
///The simplest way to execute the algorithm is to use
|
deba@1912
|
391 |
///one of the member functions called \c run(...).
|
deba@1912
|
392 |
|
deba@1912
|
393 |
///@{
|
deba@1912
|
394 |
|
deba@1912
|
395 |
///Initializes the internal data structures.
|
deba@1912
|
396 |
|
deba@1912
|
397 |
///Initializes the internal data structures.
|
deba@1912
|
398 |
///
|
deba@1912
|
399 |
void init(){
|
deba@1912
|
400 |
create_maps();
|
deba@1912
|
401 |
for(typename Graph::UEdgeIt i(*graph);i!=INVALID;++i){
|
deba@1912
|
402 |
_tree->set(i,false);
|
deba@1912
|
403 |
}
|
deba@1912
|
404 |
}
|
deba@1912
|
405 |
|
deba@1912
|
406 |
///Executes the algorithm.
|
deba@1912
|
407 |
|
deba@1912
|
408 |
///Executes the algorithm.
|
deba@1912
|
409 |
///
|
deba@1912
|
410 |
///\pre init() must be called and at least one node should be added
|
deba@1912
|
411 |
///with addSource() before using this function.
|
deba@1912
|
412 |
///
|
deba@1912
|
413 |
///This method runs the %FredmanTarjan algorithm from the node(s)
|
deba@1912
|
414 |
///in order to compute the
|
deba@1912
|
415 |
///minimum spanning tree.
|
deba@1912
|
416 |
void start(){
|
deba@1912
|
417 |
phase(*graph,identityMap<UEdge>(),countEdges(*graph));
|
deba@1912
|
418 |
}
|
deba@1912
|
419 |
|
deba@1912
|
420 |
///Runs %FredmanTarjan algorithm.
|
deba@1912
|
421 |
|
deba@1912
|
422 |
///This method runs the %FredmanTarjan algorithm
|
deba@1912
|
423 |
///in order to compute the minimum spanning forest.
|
deba@1912
|
424 |
///
|
deba@1912
|
425 |
///\note ft.run() is just a shortcut of the following code.
|
deba@1912
|
426 |
///\code
|
deba@1912
|
427 |
/// ft.init();
|
deba@1912
|
428 |
/// ft.start();
|
deba@1912
|
429 |
///\endcode
|
deba@1912
|
430 |
void run() {
|
deba@1912
|
431 |
init();
|
deba@1912
|
432 |
start();
|
deba@1912
|
433 |
}
|
deba@1912
|
434 |
|
deba@1912
|
435 |
///@}
|
deba@1912
|
436 |
|
deba@1912
|
437 |
///\name Query Functions
|
deba@1912
|
438 |
///The result of the %FredmanTarjan algorithm can be obtained using these
|
deba@1912
|
439 |
///functions.\n
|
deba@1912
|
440 |
///Before the use of these functions,
|
deba@1912
|
441 |
///either run() or start() must be called.
|
deba@1912
|
442 |
|
deba@1912
|
443 |
///@{
|
deba@1912
|
444 |
|
deba@1912
|
445 |
///Returns a reference to the tree edges map.
|
deba@1912
|
446 |
|
deba@1912
|
447 |
///Returns a reference to the TreeEdgeMap of the edges of the
|
deba@1912
|
448 |
///minimum spanning tree. The value of the map is \c true only if the
|
deba@1912
|
449 |
///edge is in the minimum spanning tree.
|
deba@1912
|
450 |
///
|
deba@1912
|
451 |
///\pre \ref run() or \ref start() must be called before using this
|
deba@1912
|
452 |
///function.
|
deba@1912
|
453 |
const TreeMap &treeMap() const { return *_tree;}
|
deba@1912
|
454 |
|
deba@1912
|
455 |
///Sets the tree edges map.
|
deba@1912
|
456 |
|
deba@1912
|
457 |
///Sets the TreeMap of the edges of the minimum spanning tree.
|
deba@1912
|
458 |
///The map values belonging to the edges of the minimum
|
deba@1912
|
459 |
///spanning tree are set to \param tree_edge_value or \c true by default
|
deba@1912
|
460 |
///while the edge values not belonging to the minimum spanning tree are
|
deba@1912
|
461 |
///set to
|
deba@1912
|
462 |
///\param tree_default_value or \c false by default.
|
deba@1912
|
463 |
///
|
deba@1912
|
464 |
///\pre \ref run() or \ref start() must be called before using this
|
deba@1912
|
465 |
///function.
|
deba@1912
|
466 |
|
deba@1912
|
467 |
template<class TreeMap>
|
deba@1912
|
468 |
void treeEdges(
|
deba@1912
|
469 |
TreeMap& tree,
|
deba@1912
|
470 |
const typename TreeMap::Value& tree_edge_value=true,
|
deba@1912
|
471 |
const typename TreeMap::Value& tree_default_value=false) const {
|
deba@1912
|
472 |
for(typename UGraph::UEdgeIt i(*graph);i!=INVALID;++i){
|
deba@1912
|
473 |
(*_tree)[i]?tree.set(i,tree_edge_value):tree.set(i,tree_default_value);
|
deba@1912
|
474 |
}
|
deba@1912
|
475 |
}
|
deba@1912
|
476 |
|
deba@1912
|
477 |
///\brief Checks if an edge is in the spanning tree or not.
|
deba@1912
|
478 |
|
deba@1912
|
479 |
///Checks if an edge is in the spanning tree or not.
|
deba@1912
|
480 |
///\param e is the edge that will be checked
|
deba@1912
|
481 |
///\return \c true if e is in the spanning tree, \c false otherwise
|
deba@1912
|
482 |
bool tree(UEdge e){
|
deba@1912
|
483 |
return (*_tree)[e];
|
deba@1912
|
484 |
}
|
deba@1912
|
485 |
///@}
|
deba@1912
|
486 |
};
|
deba@1912
|
487 |
|
deba@1912
|
488 |
/// \ingroup spantree
|
deba@1912
|
489 |
///
|
deba@1912
|
490 |
/// \brief Function type interface for FredmanTarjan algorithm.
|
deba@1912
|
491 |
///
|
deba@1912
|
492 |
/// Function type interface for FredmanTarjan algorithm.
|
deba@1912
|
493 |
/// \param graph the UGraph that the algorithm runs on
|
deba@1912
|
494 |
/// \param cost the CostMap of the edges
|
deba@1912
|
495 |
/// \retval tree the EdgeMap that contains whether an edge is in the
|
deba@1912
|
496 |
/// spanning tree or not
|
deba@1912
|
497 |
///
|
deba@1912
|
498 |
/// \sa Prim
|
deba@1912
|
499 |
template<class Graph,class CostMap,class TreeMap>
|
deba@1912
|
500 |
void fredmanTarjan(const Graph& graph, const CostMap& cost,TreeMap& tree){
|
deba@1912
|
501 |
typename FredmanTarjan<Graph,CostMap>::template DefTreeMap<TreeMap>::
|
deba@1912
|
502 |
Create ft(graph,cost);
|
deba@1912
|
503 |
ft.treeMap(tree);
|
deba@1912
|
504 |
ft.run();
|
deba@1912
|
505 |
};
|
deba@1912
|
506 |
|
deba@1912
|
507 |
} //END OF NAMESPACE LEMON
|
deba@1912
|
508 |
|
deba@1912
|
509 |
#endif
|