| [602] | 1 | // -*- c++ -*- | 
|---|
| [921] | 2 | #ifndef LEMON_BFS_DFS_H | 
|---|
 | 3 | #define LEMON_BFS_DFS_H | 
|---|
| [602] | 4 |  | 
|---|
| [615] | 5 | /// \ingroup galgs | 
|---|
 | 6 | /// \file | 
|---|
 | 7 | /// \brief Bfs and dfs iterators. | 
|---|
| [604] | 8 | /// | 
|---|
| [615] | 9 | /// This file contains bfs and dfs iterator classes. | 
|---|
| [604] | 10 | /// | 
|---|
| [615] | 11 | // /// \author Marton Makai | 
|---|
| [604] | 12 |  | 
|---|
| [602] | 13 | #include <queue> | 
|---|
 | 14 | #include <stack> | 
|---|
 | 15 | #include <utility> | 
|---|
 | 16 |  | 
|---|
| [921] | 17 | #include <lemon/invalid.h> | 
|---|
| [602] | 18 |  | 
|---|
| [921] | 19 | namespace lemon { | 
|---|
| [602] | 20 |  | 
|---|
 | 21 |   /// Bfs searches for the nodes wich are not marked in  | 
|---|
 | 22 |   /// \c reached_map | 
|---|
| [650] | 23 |   /// Reached have to be a read-write bool node-map. | 
|---|
| [615] | 24 |   /// \ingroup galgs | 
|---|
| [602] | 25 |   template <typename Graph, /*typename OutEdgeIt,*/  | 
|---|
 | 26 |             typename ReachedMap/*=typename Graph::NodeMap<bool>*/ > | 
|---|
 | 27 |   class BfsIterator { | 
|---|
 | 28 |   protected: | 
|---|
 | 29 |     typedef typename Graph::Node Node; | 
|---|
| [777] | 30 |     typedef typename Graph::Edge Edge; | 
|---|
| [602] | 31 |     typedef typename Graph::OutEdgeIt OutEdgeIt; | 
|---|
 | 32 |     const Graph* graph; | 
|---|
 | 33 |     std::queue<Node> bfs_queue; | 
|---|
 | 34 |     ReachedMap& reached; | 
|---|
 | 35 |     bool b_node_newly_reached; | 
|---|
| [777] | 36 |     Edge actual_edge; | 
|---|
| [602] | 37 |     bool own_reached_map; | 
|---|
 | 38 |   public: | 
|---|
 | 39 |     /// In that constructor \c _reached have to be a reference  | 
|---|
| [650] | 40 |     /// for a bool bode-map. The algorithm will search for the  | 
|---|
 | 41 |     /// initially \c false nodes  | 
|---|
 | 42 |     /// in a bfs order. | 
|---|
| [602] | 43 |     BfsIterator(const Graph& _graph, ReachedMap& _reached) :  | 
|---|
 | 44 |       graph(&_graph), reached(_reached),  | 
|---|
 | 45 |       own_reached_map(false) { } | 
|---|
 | 46 |     /// The same as above, but the map storing the reached nodes  | 
|---|
 | 47 |     /// is constructed dynamically to everywhere false. | 
|---|
| [650] | 48 |     /// \deprecated | 
|---|
| [602] | 49 |     BfsIterator(const Graph& _graph) :  | 
|---|
 | 50 |       graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),  | 
|---|
 | 51 |       own_reached_map(true) { } | 
|---|
| [604] | 52 |     /// The map storing the reached nodes have to be destroyed if  | 
|---|
| [602] | 53 |     /// it was constructed dynamically | 
|---|
 | 54 |     ~BfsIterator() { if (own_reached_map) delete &reached; } | 
|---|
 | 55 |     /// This method markes \c s reached. | 
|---|
 | 56 |     /// If the queue is empty, then \c s is pushed in the bfs queue  | 
|---|
 | 57 |     /// and the first out-edge is processed. | 
|---|
 | 58 |     /// If the queue is not empty, then \c s is simply pushed. | 
|---|
| [777] | 59 |     BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& pushAndSetReached(Node s) {  | 
|---|
| [602] | 60 |       reached.set(s, true); | 
|---|
 | 61 |       if (bfs_queue.empty()) { | 
|---|
 | 62 |         bfs_queue.push(s); | 
|---|
| [777] | 63 |         actual_edge=OutEdgeIt(*graph, s); | 
|---|
 | 64 |         //graph->first(actual_edge, s); | 
|---|
| [774] | 65 |         if (actual_edge!=INVALID) {  | 
|---|
| [986] | 66 |           Node w=graph->target(actual_edge); | 
|---|
| [602] | 67 |           if (!reached[w]) { | 
|---|
 | 68 |             bfs_queue.push(w); | 
|---|
 | 69 |             reached.set(w, true); | 
|---|
 | 70 |             b_node_newly_reached=true; | 
|---|
 | 71 |           } else { | 
|---|
 | 72 |             b_node_newly_reached=false; | 
|---|
 | 73 |           } | 
|---|
 | 74 |         }  | 
|---|
 | 75 |       } else { | 
|---|
 | 76 |         bfs_queue.push(s); | 
|---|
 | 77 |       } | 
|---|
| [777] | 78 |       return *this; | 
|---|
| [602] | 79 |     } | 
|---|
 | 80 |     /// As \c BfsIterator<Graph, ReachedMap> works as an edge-iterator,  | 
|---|
 | 81 |     /// its \c operator++() iterates on the edges in a bfs order. | 
|---|
 | 82 |     BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&  | 
|---|
 | 83 |     operator++() {  | 
|---|
| [774] | 84 |       if (actual_edge!=INVALID) {  | 
|---|
| [777] | 85 |         actual_edge=++OutEdgeIt(*graph, actual_edge); | 
|---|
 | 86 |         //++actual_edge; | 
|---|
| [774] | 87 |         if (actual_edge!=INVALID) { | 
|---|
| [986] | 88 |           Node w=graph->target(actual_edge); | 
|---|
| [602] | 89 |           if (!reached[w]) { | 
|---|
 | 90 |             bfs_queue.push(w); | 
|---|
 | 91 |             reached.set(w, true); | 
|---|
 | 92 |             b_node_newly_reached=true; | 
|---|
 | 93 |           } else { | 
|---|
 | 94 |             b_node_newly_reached=false; | 
|---|
 | 95 |           } | 
|---|
 | 96 |         } | 
|---|
 | 97 |       } else { | 
|---|
 | 98 |         bfs_queue.pop();  | 
|---|
 | 99 |         if (!bfs_queue.empty()) { | 
|---|
| [777] | 100 |           actual_edge=OutEdgeIt(*graph, bfs_queue.front()); | 
|---|
 | 101 |           //graph->first(actual_edge, bfs_queue.front()); | 
|---|
| [774] | 102 |           if (actual_edge!=INVALID) { | 
|---|
| [986] | 103 |             Node w=graph->target(actual_edge); | 
|---|
| [602] | 104 |             if (!reached[w]) { | 
|---|
 | 105 |               bfs_queue.push(w); | 
|---|
 | 106 |               reached.set(w, true); | 
|---|
 | 107 |               b_node_newly_reached=true; | 
|---|
 | 108 |             } else { | 
|---|
 | 109 |               b_node_newly_reached=false; | 
|---|
 | 110 |             } | 
|---|
 | 111 |           } | 
|---|
 | 112 |         } | 
|---|
 | 113 |       } | 
|---|
 | 114 |       return *this; | 
|---|
 | 115 |     } | 
|---|
| [646] | 116 |     /// Returns true iff the algorithm is finished. | 
|---|
| [602] | 117 |     bool finished() const { return bfs_queue.empty(); } | 
|---|
 | 118 |     /// The conversion operator makes for converting the bfs-iterator  | 
|---|
 | 119 |     /// to an \c out-edge-iterator. | 
|---|
| [921] | 120 |     ///\bug Edge have to be in LEMON 0.2 | 
|---|
| [777] | 121 |     operator Edge() const { return actual_edge; } | 
|---|
| [646] | 122 |     /// Returns if b-node has been reached just now. | 
|---|
| [602] | 123 |     bool isBNodeNewlyReached() const { return b_node_newly_reached; } | 
|---|
| [646] | 124 |     /// Returns if a-node is examined. | 
|---|
| [774] | 125 |     bool isANodeExamined() const { return actual_edge==INVALID; } | 
|---|
| [646] | 126 |     /// Returns a-node of the actual edge, so does if the edge is invalid. | 
|---|
| [986] | 127 |     Node source() const { return bfs_queue.front(); } | 
|---|
| [646] | 128 |     /// \pre The actual edge have to be valid. | 
|---|
| [986] | 129 |     Node target() const { return graph->target(actual_edge); } | 
|---|
| [615] | 130 |     /// Guess what? | 
|---|
| [650] | 131 |     /// \deprecated  | 
|---|
| [602] | 132 |     const ReachedMap& getReachedMap() const { return reached; } | 
|---|
| [615] | 133 |     /// Guess what? | 
|---|
| [650] | 134 |     /// \deprecated | 
|---|
| [602] | 135 |     const std::queue<Node>& getBfsQueue() const { return bfs_queue; } | 
|---|
| [615] | 136 |   }; | 
|---|
| [602] | 137 |  | 
|---|
 | 138 |   /// Bfs searches for the nodes wich are not marked in  | 
|---|
 | 139 |   /// \c reached_map | 
|---|
 | 140 |   /// Reached have to work as a read-write bool Node-map,  | 
|---|
| [650] | 141 |   /// Pred is a write edge node-map and | 
|---|
 | 142 |   /// Dist is a read-write node-map of integral value, have to be.  | 
|---|
| [615] | 143 |   /// \ingroup galgs | 
|---|
| [602] | 144 |   template <typename Graph,  | 
|---|
 | 145 |             typename ReachedMap=typename Graph::template NodeMap<bool>,  | 
|---|
 | 146 |             typename PredMap | 
|---|
 | 147 |             =typename Graph::template NodeMap<typename Graph::Edge>,  | 
|---|
 | 148 |             typename DistMap=typename Graph::template NodeMap<int> >  | 
|---|
 | 149 |   class Bfs : public BfsIterator<Graph, ReachedMap> { | 
|---|
 | 150 |     typedef BfsIterator<Graph, ReachedMap> Parent; | 
|---|
 | 151 |   protected: | 
|---|
 | 152 |     typedef typename Parent::Node Node; | 
|---|
 | 153 |     PredMap& pred; | 
|---|
 | 154 |     DistMap& dist; | 
|---|
 | 155 |   public: | 
|---|
 | 156 |     /// The algorithm will search in a bfs order for  | 
|---|
 | 157 |     /// the nodes which are \c false initially.  | 
|---|
 | 158 |     /// The constructor makes no initial changes on the maps. | 
|---|
| [671] | 159 |     Bfs<Graph, ReachedMap, PredMap, DistMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred, DistMap& _dist) :  | 
|---|
 | 160 |       BfsIterator<Graph, ReachedMap>(_graph, _reached),  | 
|---|
 | 161 |       pred(_pred), dist(_dist) { } | 
|---|
| [602] | 162 |     /// \c s is marked to be reached and pushed in the bfs queue. | 
|---|
 | 163 |     /// If the queue is empty, then the first out-edge is processed. | 
|---|
 | 164 |     /// If \c s was not marked previously, then  | 
|---|
 | 165 |     /// in addition its pred is set to be \c INVALID, and dist to \c 0.  | 
|---|
 | 166 |     /// if \c s was marked previuosly, then it is simply pushed. | 
|---|
| [777] | 167 |     Bfs<Graph, ReachedMap, PredMap, DistMap>& push(Node s) {  | 
|---|
| [602] | 168 |       if (this->reached[s]) { | 
|---|
 | 169 |         Parent::pushAndSetReached(s); | 
|---|
 | 170 |       } else { | 
|---|
 | 171 |         Parent::pushAndSetReached(s); | 
|---|
 | 172 |         pred.set(s, INVALID); | 
|---|
 | 173 |         dist.set(s, 0); | 
|---|
 | 174 |       } | 
|---|
| [777] | 175 |       return *this; | 
|---|
| [602] | 176 |     } | 
|---|
 | 177 |     /// A bfs is processed from \c s. | 
|---|
| [777] | 178 |     Bfs<Graph, ReachedMap, PredMap, DistMap>& run(Node s) { | 
|---|
| [602] | 179 |       push(s); | 
|---|
 | 180 |       while (!this->finished()) this->operator++(); | 
|---|
| [777] | 181 |       return *this; | 
|---|
| [602] | 182 |     } | 
|---|
 | 183 |     /// Beside the bfs iteration, \c pred and \dist are saved in a  | 
|---|
 | 184 |     /// newly reached node.  | 
|---|
| [604] | 185 |     Bfs<Graph, ReachedMap, PredMap, DistMap>& operator++() { | 
|---|
| [602] | 186 |       Parent::operator++(); | 
|---|
 | 187 |       if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)  | 
|---|
 | 188 |       { | 
|---|
| [986] | 189 |         pred.set(this->target(), this->actual_edge); | 
|---|
 | 190 |         dist.set(this->target(), dist[this->source()]); | 
|---|
| [602] | 191 |       } | 
|---|
 | 192 |       return *this; | 
|---|
 | 193 |     } | 
|---|
| [615] | 194 |     /// Guess what? | 
|---|
| [650] | 195 |     /// \deprecated  | 
|---|
| [602] | 196 |     const PredMap& getPredMap() const { return pred; } | 
|---|
| [615] | 197 |     /// Guess what? | 
|---|
| [650] | 198 |     /// \deprecated | 
|---|
| [602] | 199 |     const DistMap& getDistMap() const { return dist; } | 
|---|
 | 200 |   }; | 
|---|
 | 201 |  | 
|---|
 | 202 |   /// Dfs searches for the nodes wich are not marked in  | 
|---|
 | 203 |   /// \c reached_map | 
|---|
 | 204 |   /// Reached have to be a read-write bool Node-map. | 
|---|
| [615] | 205 |   /// \ingroup galgs | 
|---|
| [602] | 206 |   template <typename Graph, /*typename OutEdgeIt,*/  | 
|---|
 | 207 |             typename ReachedMap/*=typename Graph::NodeMap<bool>*/ > | 
|---|
 | 208 |   class DfsIterator { | 
|---|
 | 209 |   protected: | 
|---|
 | 210 |     typedef typename Graph::Node Node; | 
|---|
| [777] | 211 |     typedef typename Graph::Edge Edge; | 
|---|
| [602] | 212 |     typedef typename Graph::OutEdgeIt OutEdgeIt; | 
|---|
 | 213 |     const Graph* graph; | 
|---|
 | 214 |     std::stack<OutEdgeIt> dfs_stack; | 
|---|
 | 215 |     bool b_node_newly_reached; | 
|---|
| [777] | 216 |     Edge actual_edge; | 
|---|
| [602] | 217 |     Node actual_node; | 
|---|
 | 218 |     ReachedMap& reached; | 
|---|
 | 219 |     bool own_reached_map; | 
|---|
 | 220 |   public: | 
|---|
 | 221 |     /// In that constructor \c _reached have to be a reference  | 
|---|
| [650] | 222 |     /// for a bool node-map. The algorithm will search in a dfs order for  | 
|---|
| [602] | 223 |     /// the nodes which are \c false initially | 
|---|
 | 224 |     DfsIterator(const Graph& _graph, ReachedMap& _reached) :  | 
|---|
 | 225 |       graph(&_graph), reached(_reached),  | 
|---|
 | 226 |       own_reached_map(false) { } | 
|---|
 | 227 |     /// The same as above, but the map of reached nodes is  | 
|---|
 | 228 |     /// constructed dynamically  | 
|---|
 | 229 |     /// to everywhere false. | 
|---|
 | 230 |     DfsIterator(const Graph& _graph) :  | 
|---|
 | 231 |       graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),  | 
|---|
 | 232 |       own_reached_map(true) { } | 
|---|
 | 233 |     ~DfsIterator() { if (own_reached_map) delete &reached; } | 
|---|
 | 234 |     /// This method markes s reached and first out-edge is processed. | 
|---|
| [777] | 235 |     DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& pushAndSetReached(Node s) {  | 
|---|
| [602] | 236 |       actual_node=s; | 
|---|
 | 237 |       reached.set(s, true); | 
|---|
| [777] | 238 |       OutEdgeIt e(*graph, s); | 
|---|
 | 239 |       //graph->first(e, s); | 
|---|
| [602] | 240 |       dfs_stack.push(e);  | 
|---|
| [777] | 241 |       return *this; | 
|---|
| [602] | 242 |     } | 
|---|
 | 243 |     /// As \c DfsIterator<Graph, ReachedMap> works as an edge-iterator,  | 
|---|
 | 244 |     /// its \c operator++() iterates on the edges in a dfs order. | 
|---|
 | 245 |     DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&  | 
|---|
 | 246 |     operator++() {  | 
|---|
 | 247 |       actual_edge=dfs_stack.top(); | 
|---|
| [774] | 248 |       if (actual_edge!=INVALID/*.valid()*/) {  | 
|---|
| [986] | 249 |         Node w=graph->target(actual_edge); | 
|---|
| [602] | 250 |         actual_node=w; | 
|---|
 | 251 |         if (!reached[w]) { | 
|---|
| [777] | 252 |           OutEdgeIt e(*graph, w); | 
|---|
 | 253 |           //graph->first(e, w); | 
|---|
| [602] | 254 |           dfs_stack.push(e); | 
|---|
 | 255 |           reached.set(w, true); | 
|---|
 | 256 |           b_node_newly_reached=true; | 
|---|
 | 257 |         } else { | 
|---|
| [986] | 258 |           actual_node=graph->source(actual_edge); | 
|---|
| [774] | 259 |           ++dfs_stack.top(); | 
|---|
| [602] | 260 |           b_node_newly_reached=false; | 
|---|
 | 261 |         } | 
|---|
 | 262 |       } else { | 
|---|
 | 263 |         //actual_node=G.aNode(dfs_stack.top()); | 
|---|
 | 264 |         dfs_stack.pop(); | 
|---|
 | 265 |       } | 
|---|
 | 266 |       return *this; | 
|---|
 | 267 |     } | 
|---|
| [646] | 268 |     /// Returns true iff the algorithm is finished. | 
|---|
| [602] | 269 |     bool finished() const { return dfs_stack.empty(); } | 
|---|
| [646] | 270 |     /// The conversion operator makes for converting the bfs-iterator  | 
|---|
 | 271 |     /// to an \c out-edge-iterator. | 
|---|
| [921] | 272 |     ///\bug Edge have to be in LEMON 0.2 | 
|---|
| [777] | 273 |     operator Edge() const { return actual_edge; } | 
|---|
| [646] | 274 |     /// Returns if b-node has been reached just now. | 
|---|
| [602] | 275 |     bool isBNodeNewlyReached() const { return b_node_newly_reached; } | 
|---|
| [646] | 276 |     /// Returns if a-node is examined. | 
|---|
| [774] | 277 |     bool isANodeExamined() const { return actual_edge==INVALID; } | 
|---|
| [646] | 278 |     /// Returns a-node of the actual edge, so does if the edge is invalid. | 
|---|
| [986] | 279 |     Node source() const { return actual_node; /*FIXME*/} | 
|---|
| [646] | 280 |     /// Returns b-node of the actual edge.  | 
|---|
 | 281 |     /// \pre The actual edge have to be valid. | 
|---|
| [986] | 282 |     Node target() const { return graph->target(actual_edge); } | 
|---|
| [615] | 283 |     /// Guess what? | 
|---|
| [650] | 284 |     /// \deprecated | 
|---|
| [602] | 285 |     const ReachedMap& getReachedMap() const { return reached; } | 
|---|
| [615] | 286 |     /// Guess what? | 
|---|
| [650] | 287 |     /// \deprecated | 
|---|
| [602] | 288 |     const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; } | 
|---|
 | 289 |   }; | 
|---|
 | 290 |  | 
|---|
 | 291 |   /// Dfs searches for the nodes wich are not marked in  | 
|---|
 | 292 |   /// \c reached_map | 
|---|
| [650] | 293 |   /// Reached is a read-write bool node-map,  | 
|---|
 | 294 |   /// Pred is a write node-map, have to be. | 
|---|
| [615] | 295 |   /// \ingroup galgs | 
|---|
| [602] | 296 |   template <typename Graph,  | 
|---|
 | 297 |             typename ReachedMap=typename Graph::template NodeMap<bool>,  | 
|---|
 | 298 |             typename PredMap | 
|---|
 | 299 |             =typename Graph::template NodeMap<typename Graph::Edge> >  | 
|---|
 | 300 |   class Dfs : public DfsIterator<Graph, ReachedMap> { | 
|---|
 | 301 |     typedef DfsIterator<Graph, ReachedMap> Parent; | 
|---|
 | 302 |   protected: | 
|---|
 | 303 |     typedef typename Parent::Node Node; | 
|---|
 | 304 |     PredMap& pred; | 
|---|
 | 305 |   public: | 
|---|
 | 306 |     /// The algorithm will search in a dfs order for  | 
|---|
 | 307 |     /// the nodes which are \c false initially.  | 
|---|
 | 308 |     /// The constructor makes no initial changes on the maps. | 
|---|
| [671] | 309 |     Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(_pred) { } | 
|---|
| [602] | 310 |     /// \c s is marked to be reached and pushed in the bfs queue. | 
|---|
 | 311 |     /// If the queue is empty, then the first out-edge is processed. | 
|---|
 | 312 |     /// If \c s was not marked previously, then  | 
|---|
 | 313 |     /// in addition its pred is set to be \c INVALID.  | 
|---|
 | 314 |     /// if \c s was marked previuosly, then it is simply pushed. | 
|---|
| [777] | 315 |     Dfs<Graph, ReachedMap, PredMap>& push(Node s) {  | 
|---|
| [602] | 316 |       if (this->reached[s]) { | 
|---|
 | 317 |         Parent::pushAndSetReached(s); | 
|---|
 | 318 |       } else { | 
|---|
 | 319 |         Parent::pushAndSetReached(s); | 
|---|
 | 320 |         pred.set(s, INVALID); | 
|---|
 | 321 |       } | 
|---|
| [777] | 322 |       return *this; | 
|---|
| [602] | 323 |     } | 
|---|
 | 324 |     /// A bfs is processed from \c s. | 
|---|
| [777] | 325 |     Dfs<Graph, ReachedMap, PredMap>& run(Node s) { | 
|---|
| [602] | 326 |       push(s); | 
|---|
 | 327 |       while (!this->finished()) this->operator++(); | 
|---|
| [777] | 328 |       return *this; | 
|---|
| [602] | 329 |     } | 
|---|
 | 330 |     /// Beside the dfs iteration, \c pred is saved in a  | 
|---|
 | 331 |     /// newly reached node.  | 
|---|
| [604] | 332 |     Dfs<Graph, ReachedMap, PredMap>& operator++() { | 
|---|
| [602] | 333 |       Parent::operator++(); | 
|---|
 | 334 |       if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)  | 
|---|
 | 335 |       { | 
|---|
| [986] | 336 |         pred.set(this->target(), this->actual_edge); | 
|---|
| [602] | 337 |       } | 
|---|
 | 338 |       return *this; | 
|---|
 | 339 |     } | 
|---|
| [615] | 340 |     /// Guess what? | 
|---|
| [650] | 341 |     /// \deprecated | 
|---|
| [602] | 342 |     const PredMap& getPredMap() const { return pred; } | 
|---|
 | 343 |   }; | 
|---|
 | 344 |  | 
|---|
 | 345 |  | 
|---|
| [921] | 346 | } // namespace lemon | 
|---|
| [602] | 347 |  | 
|---|
| [921] | 348 | #endif //LEMON_BFS_DFS_H | 
|---|