marci@602
|
1 |
// -*- c++ -*-
|
alpar@921
|
2 |
#ifndef LEMON_BFS_DFS_H
|
alpar@921
|
3 |
#define LEMON_BFS_DFS_H
|
marci@602
|
4 |
|
marci@615
|
5 |
/// \ingroup galgs
|
marci@615
|
6 |
/// \file
|
marci@615
|
7 |
/// \brief Bfs and dfs iterators.
|
marci@604
|
8 |
///
|
marci@615
|
9 |
/// This file contains bfs and dfs iterator classes.
|
marci@604
|
10 |
///
|
marci@615
|
11 |
// /// \author Marton Makai
|
marci@604
|
12 |
|
marci@602
|
13 |
#include <queue>
|
marci@602
|
14 |
#include <stack>
|
marci@602
|
15 |
#include <utility>
|
marci@602
|
16 |
|
alpar@921
|
17 |
#include <lemon/invalid.h>
|
marci@602
|
18 |
|
alpar@921
|
19 |
namespace lemon {
|
marci@944
|
20 |
namespace marci {
|
marci@602
|
21 |
|
marci@602
|
22 |
/// Bfs searches for the nodes wich are not marked in
|
marci@602
|
23 |
/// \c reached_map
|
marci@944
|
24 |
/// RM have to be a read-write bool node-map.
|
marci@615
|
25 |
/// \ingroup galgs
|
marci@602
|
26 |
template <typename Graph, /*typename OutEdgeIt,*/
|
marci@944
|
27 |
typename RM/*=typename Graph::NodeMap<bool>*/ >
|
marci@602
|
28 |
class BfsIterator {
|
marci@944
|
29 |
public:
|
marci@944
|
30 |
typedef RM ReachedMap;
|
marci@602
|
31 |
protected:
|
marci@602
|
32 |
typedef typename Graph::Node Node;
|
marci@777
|
33 |
typedef typename Graph::Edge Edge;
|
marci@602
|
34 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
marci@602
|
35 |
const Graph* graph;
|
marci@602
|
36 |
std::queue<Node> bfs_queue;
|
marci@944
|
37 |
ReachedMap* reached_map;
|
marci@602
|
38 |
bool b_node_newly_reached;
|
marci@944
|
39 |
//OutEdgeIt actual_edge;
|
marci@777
|
40 |
Edge actual_edge;
|
marci@944
|
41 |
/// \e
|
marci@944
|
42 |
BfsIterator(const Graph& _graph) : graph(&_graph), reached_map(0) { }
|
marci@944
|
43 |
/// RM have to be set before any bfs operation.
|
marci@944
|
44 |
BfsIterator<Graph, RM>& setReached(RM& _reached_map) {
|
marci@944
|
45 |
reached_map=&_reached_map;
|
marci@944
|
46 |
}
|
marci@602
|
47 |
public:
|
marci@944
|
48 |
/// In that constructor \c _reached_map have to be a reference
|
marci@650
|
49 |
/// for a bool bode-map. The algorithm will search for the
|
marci@650
|
50 |
/// initially \c false nodes
|
marci@650
|
51 |
/// in a bfs order.
|
marci@944
|
52 |
BfsIterator(const Graph& _graph, ReachedMap& _reached_map) :
|
marci@944
|
53 |
graph(&_graph), reached_map(&_reached_map) { }
|
marci@602
|
54 |
/// The same as above, but the map storing the reached nodes
|
marci@602
|
55 |
/// is constructed dynamically to everywhere false.
|
marci@650
|
56 |
/// \deprecated
|
marci@944
|
57 |
// BfsIterator(const Graph& _graph) :
|
marci@944
|
58 |
// graph(&_graph), reached_map(new ReachedMap(*graph /*, false*/)),
|
marci@944
|
59 |
// own_reached_map(true) { }
|
marci@944
|
60 |
// /// The map storing the reached nodes have to be destroyed if
|
marci@944
|
61 |
// /// it was constructed dynamically
|
marci@944
|
62 |
// ~BfsIterator() { if (own_reached_map) delete reached_map; }
|
marci@602
|
63 |
/// This method markes \c s reached.
|
marci@602
|
64 |
/// If the queue is empty, then \c s is pushed in the bfs queue
|
marci@602
|
65 |
/// and the first out-edge is processed.
|
marci@602
|
66 |
/// If the queue is not empty, then \c s is simply pushed.
|
marci@777
|
67 |
BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& pushAndSetReached(Node s) {
|
marci@944
|
68 |
reached_map->set(s, true);
|
marci@602
|
69 |
if (bfs_queue.empty()) {
|
marci@602
|
70 |
bfs_queue.push(s);
|
marci@777
|
71 |
actual_edge=OutEdgeIt(*graph, s);
|
marci@777
|
72 |
//graph->first(actual_edge, s);
|
alpar@774
|
73 |
if (actual_edge!=INVALID) {
|
alpar@986
|
74 |
Node w=graph->target(actual_edge);
|
marci@944
|
75 |
if (!(*reached_map)[w]) {
|
marci@602
|
76 |
bfs_queue.push(w);
|
marci@944
|
77 |
reached_map->set(w, true);
|
marci@602
|
78 |
b_node_newly_reached=true;
|
marci@602
|
79 |
} else {
|
marci@602
|
80 |
b_node_newly_reached=false;
|
marci@602
|
81 |
}
|
marci@602
|
82 |
}
|
marci@602
|
83 |
} else {
|
marci@602
|
84 |
bfs_queue.push(s);
|
marci@602
|
85 |
}
|
marci@777
|
86 |
return *this;
|
marci@602
|
87 |
}
|
marci@602
|
88 |
/// As \c BfsIterator<Graph, ReachedMap> works as an edge-iterator,
|
marci@602
|
89 |
/// its \c operator++() iterates on the edges in a bfs order.
|
marci@602
|
90 |
BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
|
marci@602
|
91 |
operator++() {
|
alpar@774
|
92 |
if (actual_edge!=INVALID) {
|
marci@777
|
93 |
actual_edge=++OutEdgeIt(*graph, actual_edge);
|
marci@777
|
94 |
//++actual_edge;
|
alpar@774
|
95 |
if (actual_edge!=INVALID) {
|
alpar@986
|
96 |
Node w=graph->target(actual_edge);
|
marci@944
|
97 |
if (!(*reached_map)[w]) {
|
marci@602
|
98 |
bfs_queue.push(w);
|
marci@944
|
99 |
reached_map->set(w, true);
|
marci@602
|
100 |
b_node_newly_reached=true;
|
marci@602
|
101 |
} else {
|
marci@602
|
102 |
b_node_newly_reached=false;
|
marci@602
|
103 |
}
|
marci@602
|
104 |
}
|
marci@602
|
105 |
} else {
|
marci@602
|
106 |
bfs_queue.pop();
|
marci@602
|
107 |
if (!bfs_queue.empty()) {
|
marci@777
|
108 |
actual_edge=OutEdgeIt(*graph, bfs_queue.front());
|
marci@777
|
109 |
//graph->first(actual_edge, bfs_queue.front());
|
alpar@774
|
110 |
if (actual_edge!=INVALID) {
|
alpar@986
|
111 |
Node w=graph->target(actual_edge);
|
marci@944
|
112 |
if (!(*reached_map)[w]) {
|
marci@602
|
113 |
bfs_queue.push(w);
|
marci@944
|
114 |
reached_map->set(w, true);
|
marci@602
|
115 |
b_node_newly_reached=true;
|
marci@602
|
116 |
} else {
|
marci@602
|
117 |
b_node_newly_reached=false;
|
marci@602
|
118 |
}
|
marci@602
|
119 |
}
|
marci@602
|
120 |
}
|
marci@602
|
121 |
}
|
marci@602
|
122 |
return *this;
|
marci@602
|
123 |
}
|
marci@646
|
124 |
/// Returns true iff the algorithm is finished.
|
marci@602
|
125 |
bool finished() const { return bfs_queue.empty(); }
|
marci@602
|
126 |
/// The conversion operator makes for converting the bfs-iterator
|
marci@602
|
127 |
/// to an \c out-edge-iterator.
|
alpar@921
|
128 |
///\bug Edge have to be in LEMON 0.2
|
marci@777
|
129 |
operator Edge() const { return actual_edge; }
|
marci@646
|
130 |
/// Returns if b-node has been reached just now.
|
marci@602
|
131 |
bool isBNodeNewlyReached() const { return b_node_newly_reached; }
|
marci@646
|
132 |
/// Returns if a-node is examined.
|
alpar@774
|
133 |
bool isANodeExamined() const { return actual_edge==INVALID; }
|
marci@646
|
134 |
/// Returns a-node of the actual edge, so does if the edge is invalid.
|
alpar@986
|
135 |
Node source() const { return bfs_queue.front(); }
|
marci@646
|
136 |
/// \pre The actual edge have to be valid.
|
alpar@986
|
137 |
Node target() const { return graph->target(actual_edge); }
|
marci@615
|
138 |
/// Guess what?
|
marci@650
|
139 |
/// \deprecated
|
marci@944
|
140 |
const ReachedMap& reachedMap() const { return *reached_map; }
|
marci@944
|
141 |
/// Guess what?
|
marci@944
|
142 |
/// \deprecated
|
alpar@987
|
143 |
typename ReachedMap::Value reached(const Node& n) const {
|
marci@944
|
144 |
return (*reached_map)[n];
|
marci@944
|
145 |
}
|
marci@615
|
146 |
/// Guess what?
|
marci@650
|
147 |
/// \deprecated
|
marci@602
|
148 |
const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
|
marci@615
|
149 |
};
|
marci@602
|
150 |
|
marci@602
|
151 |
/// Bfs searches for the nodes wich are not marked in
|
marci@602
|
152 |
/// \c reached_map
|
marci@944
|
153 |
/// RM have to work as a read-write bool Node-map,
|
marci@944
|
154 |
/// PM is a write edge node-map and
|
marci@944
|
155 |
/// PNM is a write node node-map and
|
marci@944
|
156 |
/// DM is a read-write node-map of integral value, have to be.
|
marci@615
|
157 |
/// \ingroup galgs
|
marci@602
|
158 |
template <typename Graph,
|
marci@944
|
159 |
typename RM=typename Graph::template NodeMap<bool>,
|
marci@944
|
160 |
typename PM
|
marci@602
|
161 |
=typename Graph::template NodeMap<typename Graph::Edge>,
|
marci@944
|
162 |
typename PNM
|
marci@944
|
163 |
=typename Graph::template NodeMap<typename Graph::Node>,
|
marci@944
|
164 |
typename DM=typename Graph::template NodeMap<int> >
|
marci@944
|
165 |
class Bfs : public BfsIterator<Graph, RM> {
|
marci@944
|
166 |
typedef BfsIterator<Graph, RM> Parent;
|
marci@944
|
167 |
public:
|
marci@944
|
168 |
typedef RM ReachedMap;
|
marci@944
|
169 |
typedef PM PredMap;
|
marci@944
|
170 |
typedef PNM PredNodeMap;
|
marci@944
|
171 |
typedef DM DistMap;
|
marci@602
|
172 |
protected:
|
marci@602
|
173 |
typedef typename Parent::Node Node;
|
marci@944
|
174 |
PredMap* pred_map;
|
marci@944
|
175 |
PredNodeMap* pred_node_map;
|
marci@944
|
176 |
DistMap* dist_map;
|
marci@944
|
177 |
/// \e
|
marci@944
|
178 |
Bfs<Graph, RM, PM, PNM, DM>
|
marci@944
|
179 |
(const Graph& _graph) : BfsIterator<Graph, RM>(_graph) { }
|
marci@944
|
180 |
/// PM have to be set before any bfs operation.
|
marci@944
|
181 |
Bfs<Graph, RM, PM, PNM, DM>&
|
marci@944
|
182 |
setPredMap(PredMap& _pred_map) {
|
marci@944
|
183 |
pred_map=&_pred_map;
|
marci@944
|
184 |
}
|
marci@944
|
185 |
/// PredNodeMap have to be set before any bfs operation.
|
marci@944
|
186 |
Bfs<Graph, RM, PM, PNM, DM>&
|
marci@944
|
187 |
setPredNodeMap(PredNodeMap& _pred_node_map) {
|
marci@944
|
188 |
pred_node_map=&_pred_node_map;
|
marci@944
|
189 |
}
|
marci@944
|
190 |
/// DistMap have to be set before any bfs operation.
|
marci@944
|
191 |
Bfs<Graph, RM, PM, PNM, DM>&
|
marci@944
|
192 |
setDistMap(DistMap& _dist_map) {
|
marci@944
|
193 |
dist_map=&_dist_map;
|
marci@944
|
194 |
}
|
marci@602
|
195 |
public:
|
marci@602
|
196 |
/// The algorithm will search in a bfs order for
|
marci@602
|
197 |
/// the nodes which are \c false initially.
|
marci@602
|
198 |
/// The constructor makes no initial changes on the maps.
|
marci@944
|
199 |
Bfs<Graph, RM, PM, PNM, DM>
|
marci@944
|
200 |
(const Graph& _graph, ReachedMap& _reached_map,
|
marci@944
|
201 |
PredMap& _pred_map, PredNodeMap& _pred_node_map,
|
marci@944
|
202 |
DistMap& _dist_map) : BfsIterator<Graph, RM>(_graph, _reached_map),
|
marci@944
|
203 |
pred_map(&_pred_map), pred_node_map(&_pred_node_map),
|
marci@944
|
204 |
dist_map(&_dist_map) { }
|
marci@602
|
205 |
/// \c s is marked to be reached and pushed in the bfs queue.
|
marci@602
|
206 |
/// If the queue is empty, then the first out-edge is processed.
|
marci@602
|
207 |
/// If \c s was not marked previously, then
|
marci@944
|
208 |
/// in addition its pred_map is set to be \c INVALID,
|
marci@944
|
209 |
/// and dist_map to \c 0.
|
marci@602
|
210 |
/// if \c s was marked previuosly, then it is simply pushed.
|
marci@944
|
211 |
Bfs<Graph, RM, PM, PNM, DM>& push(Node s) {
|
marci@944
|
212 |
if ((*(this->reached_map))[s]) {
|
marci@602
|
213 |
Parent::pushAndSetReached(s);
|
marci@602
|
214 |
} else {
|
marci@602
|
215 |
Parent::pushAndSetReached(s);
|
marci@944
|
216 |
pred_map->set(s, INVALID);
|
marci@944
|
217 |
pred_node_map->set(s, INVALID);
|
marci@944
|
218 |
dist_map->set(s, 0);
|
marci@602
|
219 |
}
|
marci@777
|
220 |
return *this;
|
marci@602
|
221 |
}
|
marci@602
|
222 |
/// A bfs is processed from \c s.
|
marci@944
|
223 |
Bfs<Graph, RM, PM, PNM, DM>& run(Node s) {
|
marci@602
|
224 |
push(s);
|
marci@602
|
225 |
while (!this->finished()) this->operator++();
|
marci@777
|
226 |
return *this;
|
marci@602
|
227 |
}
|
marci@944
|
228 |
/// Beside the bfs iteration, \c pred_map and \dist_map are saved in a
|
marci@602
|
229 |
/// newly reached node.
|
marci@944
|
230 |
Bfs<Graph, RM, PM, PNM, DM>& operator++() {
|
marci@602
|
231 |
Parent::operator++();
|
marci@944
|
232 |
if ((this->actual_edge)!=INVALID && this->b_node_newly_reached)
|
marci@602
|
233 |
{
|
alpar@986
|
234 |
pred_map->set(this->target(), this->actual_edge);
|
alpar@986
|
235 |
pred_node_map->set(this->target(), this->source());
|
alpar@986
|
236 |
dist_map->set(this->target(), (*dist_map)[this->source()]);
|
marci@602
|
237 |
}
|
marci@602
|
238 |
return *this;
|
marci@602
|
239 |
}
|
marci@615
|
240 |
/// Guess what?
|
marci@650
|
241 |
/// \deprecated
|
marci@944
|
242 |
const PredMap& predMap() const { return *pred_map; }
|
marci@944
|
243 |
/// Guess what?
|
marci@944
|
244 |
/// \deprecated
|
alpar@987
|
245 |
typename PredMap::Value pred(const Node& n) const {
|
marci@944
|
246 |
return (*pred_map)[n];
|
marci@944
|
247 |
}
|
marci@944
|
248 |
/// Guess what?
|
marci@944
|
249 |
/// \deprecated
|
marci@944
|
250 |
const PredNodeMap& predNodeMap() const { return *pred_node_map; }
|
marci@944
|
251 |
/// Guess what?
|
marci@944
|
252 |
/// \deprecated
|
alpar@987
|
253 |
typename PredNodeMap::Value predNode(const Node& n) const {
|
marci@944
|
254 |
return (*pred_node_map)[n];
|
marci@944
|
255 |
}
|
marci@615
|
256 |
/// Guess what?
|
marci@650
|
257 |
/// \deprecated
|
marci@944
|
258 |
const DistMap& distMap() const { return *dist_map; }
|
marci@944
|
259 |
/// Guess what?
|
marci@944
|
260 |
/// \deprecated
|
alpar@987
|
261 |
typename DistMap::Value dist(const Node& n) const {
|
marci@944
|
262 |
return (*dist_map)[n];
|
marci@944
|
263 |
}
|
marci@602
|
264 |
};
|
marci@602
|
265 |
|
marci@944
|
266 |
// template <typename Graph,
|
marci@944
|
267 |
// typename RM=typename Graph::template NodeMap<bool>,
|
marci@944
|
268 |
// typename PM
|
marci@944
|
269 |
// =typename Graph::template NodeMap<typename Graph::Edge>,
|
marci@944
|
270 |
// typename PredNodeMap
|
marci@944
|
271 |
// =typename Graph::template NodeMap<typename Graph::Node>,
|
marci@944
|
272 |
// typename DistMap=typename Graph::template NodeMap<int> >
|
marci@944
|
273 |
// class BfsWizard : public Bfs<Graph> {
|
marci@944
|
274 |
// public:
|
marci@944
|
275 |
// typedef Bfs<Graph, PM, PredNodeMap, DistMap> Parent;
|
marci@944
|
276 |
// protected:
|
marci@944
|
277 |
// typedef typename Parent::Node Node;
|
marci@944
|
278 |
// bool own_reached_map;
|
marci@944
|
279 |
// bool own_pred_map;
|
marci@944
|
280 |
// bool own_pred_node_map;
|
marci@944
|
281 |
// bool own_dist_map;
|
marci@944
|
282 |
|
marci@944
|
283 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
284 |
// makeRreached() {
|
marci@944
|
285 |
// own_reached_map=true;
|
marci@944
|
286 |
// reached=new ReachedMap(*graph, false);
|
marci@944
|
287 |
// }
|
marci@944
|
288 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
289 |
// deleteReachedMap() {
|
marci@944
|
290 |
// own_reached_map=false;
|
marci@944
|
291 |
// delete reached;
|
marci@944
|
292 |
// }
|
marci@944
|
293 |
|
marci@944
|
294 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
295 |
// makePM() {
|
marci@944
|
296 |
// own_pred_map=true;
|
marci@944
|
297 |
// pred_map=new PM(*graph, INVALID);
|
marci@944
|
298 |
// }
|
marci@944
|
299 |
// BfsWizard<Graph, ReachedMap, PM, PredNodeMap, DistMap>&
|
marci@944
|
300 |
// deletePM() {
|
marci@944
|
301 |
// own_pred_map=false;
|
marci@944
|
302 |
// delete pred_map;
|
marci@944
|
303 |
// }
|
marci@944
|
304 |
|
marci@944
|
305 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
306 |
// makePredNodeMap() {
|
marci@944
|
307 |
// own_pred_node_map=true;
|
marci@944
|
308 |
// pred_node_map=new PredNodeMap(*graph, INVALID);
|
marci@944
|
309 |
// }
|
marci@944
|
310 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
311 |
// deletePredNodeMap() {
|
marci@944
|
312 |
// own_pred_node_map=false;
|
marci@944
|
313 |
// delete pred_node_map;
|
marci@944
|
314 |
// }
|
marci@944
|
315 |
|
marci@944
|
316 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
317 |
// makeDistMap() {
|
marci@944
|
318 |
// own_dist_map=true;
|
marci@944
|
319 |
// dist_map=new DistMap(*graph, 0);
|
marci@944
|
320 |
// }
|
marci@944
|
321 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
322 |
// deleteDistMap() {
|
marci@944
|
323 |
// own_dist_map=false;
|
marci@944
|
324 |
// delete dist_map;
|
marci@944
|
325 |
// }
|
marci@944
|
326 |
|
marci@944
|
327 |
// public:
|
marci@944
|
328 |
// /// User friendly Bfs class.
|
marci@944
|
329 |
// /// The maps which are not explicitly given by the user are
|
marci@944
|
330 |
// /// constructed with false, INVALID, INVALID and 0 values.
|
marci@944
|
331 |
// /// For the user defined maps, the values are not modified, and
|
marci@944
|
332 |
// /// the bfs is processed without any preset on maps. Therefore,
|
marci@944
|
333 |
// /// the bfs will search only the nodes which are set false previously
|
marci@944
|
334 |
// /// in reached, and in the nodes wich are not newly reached by the
|
marci@944
|
335 |
// /// search, the map values are not modified.
|
marci@944
|
336 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>
|
marci@944
|
337 |
// (const Graph& _graph) :
|
marci@944
|
338 |
// own_reached_map(false),
|
marci@944
|
339 |
// own_pred_map(false),
|
marci@944
|
340 |
// own_pred_node_map(false),
|
marci@944
|
341 |
// own_dist_map(false) {
|
marci@944
|
342 |
// }
|
marci@944
|
343 |
|
marci@944
|
344 |
// /// \e
|
marci@944
|
345 |
// ~BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>() {
|
marci@944
|
346 |
// if (own_reached_map) deleteReachedMap();
|
marci@944
|
347 |
// if (own_pred_map) deletePM();
|
marci@944
|
348 |
// if (own_pred_node_map) deletePredNodeMap();
|
marci@944
|
349 |
// if (own_dist_map) deleteDistMap();
|
marci@944
|
350 |
// }
|
marci@944
|
351 |
|
marci@944
|
352 |
// /// \e
|
marci@944
|
353 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
354 |
// setReachedMap(ReachedMap& _reached) {
|
marci@944
|
355 |
// if (own_reached_map) deleteReachedMap();
|
marci@944
|
356 |
// Parent::setReachedMap(_reached);
|
marci@944
|
357 |
// }
|
marci@944
|
358 |
// /// \e
|
marci@944
|
359 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
360 |
// setPM(PM& _pred) {
|
marci@944
|
361 |
// if (own_pred_map) deletePM();
|
marci@944
|
362 |
// Parent::setPM(_pred);
|
marci@944
|
363 |
// }
|
marci@944
|
364 |
// /// \e
|
marci@944
|
365 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
366 |
// setPredNodeMap(PredNodeMap& _pred_node) {
|
marci@944
|
367 |
// if (own_pred_node_map) deletePredNodeMap();
|
marci@944
|
368 |
// Parent::setPredNodeMap(_pred_node);
|
marci@944
|
369 |
// }
|
marci@944
|
370 |
// /// \e
|
marci@944
|
371 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
372 |
// setDistMap(DistMap& _dist) {
|
marci@944
|
373 |
// if (own_dist_map) deleteDistMap();
|
marci@944
|
374 |
// Parent::setDistMap(_dist);
|
marci@944
|
375 |
// }
|
marci@944
|
376 |
|
marci@944
|
377 |
// /// \e
|
marci@944
|
378 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
379 |
// push(Node s) {
|
marci@944
|
380 |
// if (!reached) makeReachedMap();
|
marci@944
|
381 |
// if (!pred_map) makePMMap();
|
marci@944
|
382 |
// if (!pred_node_map) makePredNodeMap();
|
marci@944
|
383 |
// if (!dist_map) makeDistMap();
|
marci@944
|
384 |
// push(s);
|
marci@944
|
385 |
// return *this;
|
marci@944
|
386 |
// }
|
marci@944
|
387 |
|
marci@944
|
388 |
// /// \e
|
marci@944
|
389 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
390 |
// operator++() {
|
marci@944
|
391 |
// if (!reached) makeRM();
|
marci@944
|
392 |
// if (!pred_map) makePMMap();
|
marci@944
|
393 |
// if (!pred_node_map) makePredNodeMap();
|
marci@944
|
394 |
// if (!dist_map) makeDistMap();
|
marci@944
|
395 |
// ++(*this);
|
marci@944
|
396 |
// return *this;
|
marci@944
|
397 |
// }
|
marci@944
|
398 |
|
marci@944
|
399 |
// /// \e
|
marci@944
|
400 |
// BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
|
marci@944
|
401 |
// run(Node s) {
|
marci@944
|
402 |
// if (!reached) makeRM();
|
marci@944
|
403 |
// if (!pred_map) makePMMap();
|
marci@944
|
404 |
// if (!pred_node_map) makePredNodeMap();
|
marci@944
|
405 |
// if (!dist_map) makeDistMap();
|
marci@944
|
406 |
// run(s);
|
marci@944
|
407 |
// return *this;
|
marci@944
|
408 |
// }
|
marci@944
|
409 |
|
marci@944
|
410 |
// };
|
marci@944
|
411 |
|
marci@944
|
412 |
|
marci@602
|
413 |
/// Dfs searches for the nodes wich are not marked in
|
marci@602
|
414 |
/// \c reached_map
|
marci@602
|
415 |
/// Reached have to be a read-write bool Node-map.
|
marci@615
|
416 |
/// \ingroup galgs
|
marci@602
|
417 |
template <typename Graph, /*typename OutEdgeIt,*/
|
marci@602
|
418 |
typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
|
marci@602
|
419 |
class DfsIterator {
|
marci@602
|
420 |
protected:
|
marci@602
|
421 |
typedef typename Graph::Node Node;
|
marci@777
|
422 |
typedef typename Graph::Edge Edge;
|
marci@602
|
423 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
marci@602
|
424 |
const Graph* graph;
|
marci@602
|
425 |
std::stack<OutEdgeIt> dfs_stack;
|
marci@602
|
426 |
bool b_node_newly_reached;
|
marci@777
|
427 |
Edge actual_edge;
|
marci@602
|
428 |
Node actual_node;
|
marci@602
|
429 |
ReachedMap& reached;
|
marci@602
|
430 |
bool own_reached_map;
|
marci@602
|
431 |
public:
|
marci@602
|
432 |
/// In that constructor \c _reached have to be a reference
|
marci@650
|
433 |
/// for a bool node-map. The algorithm will search in a dfs order for
|
marci@602
|
434 |
/// the nodes which are \c false initially
|
marci@602
|
435 |
DfsIterator(const Graph& _graph, ReachedMap& _reached) :
|
marci@602
|
436 |
graph(&_graph), reached(_reached),
|
marci@602
|
437 |
own_reached_map(false) { }
|
marci@602
|
438 |
/// The same as above, but the map of reached nodes is
|
marci@602
|
439 |
/// constructed dynamically
|
marci@602
|
440 |
/// to everywhere false.
|
marci@602
|
441 |
DfsIterator(const Graph& _graph) :
|
marci@602
|
442 |
graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),
|
marci@602
|
443 |
own_reached_map(true) { }
|
marci@602
|
444 |
~DfsIterator() { if (own_reached_map) delete &reached; }
|
marci@602
|
445 |
/// This method markes s reached and first out-edge is processed.
|
marci@777
|
446 |
DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& pushAndSetReached(Node s) {
|
marci@602
|
447 |
actual_node=s;
|
marci@602
|
448 |
reached.set(s, true);
|
marci@777
|
449 |
OutEdgeIt e(*graph, s);
|
marci@777
|
450 |
//graph->first(e, s);
|
marci@602
|
451 |
dfs_stack.push(e);
|
marci@777
|
452 |
return *this;
|
marci@602
|
453 |
}
|
marci@602
|
454 |
/// As \c DfsIterator<Graph, ReachedMap> works as an edge-iterator,
|
marci@602
|
455 |
/// its \c operator++() iterates on the edges in a dfs order.
|
marci@602
|
456 |
DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
|
marci@602
|
457 |
operator++() {
|
marci@602
|
458 |
actual_edge=dfs_stack.top();
|
alpar@774
|
459 |
if (actual_edge!=INVALID/*.valid()*/) {
|
alpar@986
|
460 |
Node w=graph->target(actual_edge);
|
marci@602
|
461 |
actual_node=w;
|
marci@602
|
462 |
if (!reached[w]) {
|
marci@777
|
463 |
OutEdgeIt e(*graph, w);
|
marci@777
|
464 |
//graph->first(e, w);
|
marci@602
|
465 |
dfs_stack.push(e);
|
marci@602
|
466 |
reached.set(w, true);
|
marci@602
|
467 |
b_node_newly_reached=true;
|
marci@602
|
468 |
} else {
|
alpar@986
|
469 |
actual_node=graph->source(actual_edge);
|
alpar@774
|
470 |
++dfs_stack.top();
|
marci@602
|
471 |
b_node_newly_reached=false;
|
marci@602
|
472 |
}
|
marci@602
|
473 |
} else {
|
marci@602
|
474 |
//actual_node=G.aNode(dfs_stack.top());
|
marci@602
|
475 |
dfs_stack.pop();
|
marci@602
|
476 |
}
|
marci@602
|
477 |
return *this;
|
marci@602
|
478 |
}
|
marci@646
|
479 |
/// Returns true iff the algorithm is finished.
|
marci@602
|
480 |
bool finished() const { return dfs_stack.empty(); }
|
marci@646
|
481 |
/// The conversion operator makes for converting the bfs-iterator
|
marci@646
|
482 |
/// to an \c out-edge-iterator.
|
alpar@921
|
483 |
///\bug Edge have to be in LEMON 0.2
|
marci@777
|
484 |
operator Edge() const { return actual_edge; }
|
marci@646
|
485 |
/// Returns if b-node has been reached just now.
|
marci@602
|
486 |
bool isBNodeNewlyReached() const { return b_node_newly_reached; }
|
marci@646
|
487 |
/// Returns if a-node is examined.
|
alpar@774
|
488 |
bool isANodeExamined() const { return actual_edge==INVALID; }
|
marci@646
|
489 |
/// Returns a-node of the actual edge, so does if the edge is invalid.
|
alpar@986
|
490 |
Node source() const { return actual_node; /*FIXME*/}
|
marci@646
|
491 |
/// Returns b-node of the actual edge.
|
marci@646
|
492 |
/// \pre The actual edge have to be valid.
|
alpar@986
|
493 |
Node target() const { return graph->target(actual_edge); }
|
marci@615
|
494 |
/// Guess what?
|
marci@650
|
495 |
/// \deprecated
|
marci@602
|
496 |
const ReachedMap& getReachedMap() const { return reached; }
|
marci@615
|
497 |
/// Guess what?
|
marci@650
|
498 |
/// \deprecated
|
marci@602
|
499 |
const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
|
marci@602
|
500 |
};
|
marci@602
|
501 |
|
marci@602
|
502 |
/// Dfs searches for the nodes wich are not marked in
|
marci@602
|
503 |
/// \c reached_map
|
marci@650
|
504 |
/// Reached is a read-write bool node-map,
|
marci@650
|
505 |
/// Pred is a write node-map, have to be.
|
marci@615
|
506 |
/// \ingroup galgs
|
marci@602
|
507 |
template <typename Graph,
|
marci@602
|
508 |
typename ReachedMap=typename Graph::template NodeMap<bool>,
|
marci@602
|
509 |
typename PredMap
|
marci@602
|
510 |
=typename Graph::template NodeMap<typename Graph::Edge> >
|
marci@602
|
511 |
class Dfs : public DfsIterator<Graph, ReachedMap> {
|
marci@602
|
512 |
typedef DfsIterator<Graph, ReachedMap> Parent;
|
marci@602
|
513 |
protected:
|
marci@602
|
514 |
typedef typename Parent::Node Node;
|
marci@602
|
515 |
PredMap& pred;
|
marci@602
|
516 |
public:
|
marci@602
|
517 |
/// The algorithm will search in a dfs order for
|
marci@602
|
518 |
/// the nodes which are \c false initially.
|
marci@602
|
519 |
/// The constructor makes no initial changes on the maps.
|
athos@671
|
520 |
Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(_pred) { }
|
marci@602
|
521 |
/// \c s is marked to be reached and pushed in the bfs queue.
|
marci@602
|
522 |
/// If the queue is empty, then the first out-edge is processed.
|
marci@602
|
523 |
/// If \c s was not marked previously, then
|
marci@602
|
524 |
/// in addition its pred is set to be \c INVALID.
|
marci@602
|
525 |
/// if \c s was marked previuosly, then it is simply pushed.
|
marci@777
|
526 |
Dfs<Graph, ReachedMap, PredMap>& push(Node s) {
|
marci@602
|
527 |
if (this->reached[s]) {
|
marci@602
|
528 |
Parent::pushAndSetReached(s);
|
marci@602
|
529 |
} else {
|
marci@602
|
530 |
Parent::pushAndSetReached(s);
|
marci@602
|
531 |
pred.set(s, INVALID);
|
marci@602
|
532 |
}
|
marci@777
|
533 |
return *this;
|
marci@602
|
534 |
}
|
marci@602
|
535 |
/// A bfs is processed from \c s.
|
marci@777
|
536 |
Dfs<Graph, ReachedMap, PredMap>& run(Node s) {
|
marci@602
|
537 |
push(s);
|
marci@602
|
538 |
while (!this->finished()) this->operator++();
|
marci@777
|
539 |
return *this;
|
marci@602
|
540 |
}
|
marci@602
|
541 |
/// Beside the dfs iteration, \c pred is saved in a
|
marci@602
|
542 |
/// newly reached node.
|
marci@604
|
543 |
Dfs<Graph, ReachedMap, PredMap>& operator++() {
|
marci@602
|
544 |
Parent::operator++();
|
marci@602
|
545 |
if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)
|
marci@602
|
546 |
{
|
alpar@986
|
547 |
pred.set(this->target(), this->actual_edge);
|
marci@602
|
548 |
}
|
marci@602
|
549 |
return *this;
|
marci@602
|
550 |
}
|
marci@615
|
551 |
/// Guess what?
|
marci@650
|
552 |
/// \deprecated
|
marci@602
|
553 |
const PredMap& getPredMap() const { return pred; }
|
marci@602
|
554 |
};
|
marci@602
|
555 |
|
marci@944
|
556 |
} // namespace marci
|
alpar@921
|
557 |
} // namespace lemon
|
marci@602
|
558 |
|
alpar@921
|
559 |
#endif //LEMON_BFS_DFS_H
|