src/work/marci/bfs_mm.h
author alpar
Mon, 21 Feb 2005 10:08:12 +0000
changeset 1162 2f51fccbc261
parent 986 e997802b855c
permissions -rw-r--r--
New features in v0.3
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