src/hugo/dfs.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 781 d4d182ab75bd
child 906 17f31d280385
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
alpar@780
     1
// -*- C++ -*-
alpar@780
     2
#ifndef HUGO_DFS_H
alpar@780
     3
#define HUGO_DFS_H
alpar@780
     4
alpar@780
     5
///\ingroup flowalgs
alpar@780
     6
///\file
alpar@781
     7
///\brief %DFS algorithm.
alpar@780
     8
///
alpar@780
     9
///\todo Revise Manual.
alpar@780
    10
alpar@780
    11
#include <hugo/bin_heap.h>
alpar@780
    12
#include <hugo/invalid.h>
alpar@780
    13
alpar@780
    14
namespace hugo {
alpar@780
    15
alpar@780
    16
/// \addtogroup flowalgs
alpar@780
    17
/// @{
alpar@780
    18
alpar@781
    19
  ///%DFS algorithm class.
alpar@780
    20
alpar@781
    21
  ///This class provides an efficient implementation of %DFS algorithm.
alpar@780
    22
  ///
alpar@780
    23
  ///\param GR The graph type the algorithm runs on.
alpar@780
    24
  ///
alpar@781
    25
  ///\author Alpar Juttner
alpar@780
    26
alpar@780
    27
#ifdef DOXYGEN
alpar@780
    28
  template <typename GR>
alpar@780
    29
#else
alpar@780
    30
  template <typename GR>
alpar@780
    31
#endif
alpar@780
    32
  class Dfs{
alpar@780
    33
  public:
alpar@780
    34
    ///The type of the underlying graph.
alpar@780
    35
    typedef GR Graph;
alpar@802
    36
    /// .
alpar@780
    37
    typedef typename Graph::Node Node;
alpar@802
    38
    /// .
alpar@780
    39
    typedef typename Graph::NodeIt NodeIt;
alpar@802
    40
    /// .
alpar@780
    41
    typedef typename Graph::Edge Edge;
alpar@802
    42
    /// .
alpar@780
    43
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@780
    44
    
alpar@780
    45
    ///\brief The type of the map that stores the last
alpar@781
    46
    ///edges of the paths on the %DFS tree.
alpar@780
    47
    typedef typename Graph::template NodeMap<Edge> PredMap;
alpar@780
    48
    ///\brief The type of the map that stores the last but one
alpar@781
    49
    ///nodes of the paths on the %DFS tree.
alpar@780
    50
    typedef typename Graph::template NodeMap<Node> PredNodeMap;
alpar@781
    51
    ///The type of the map that stores the dists of the nodes on the %DFS tree.
alpar@780
    52
    typedef typename Graph::template NodeMap<int> DistMap;
alpar@780
    53
alpar@780
    54
  private:
alpar@802
    55
    /// Pointer to the underlying graph.
alpar@780
    56
    const Graph *G;
alpar@802
    57
    ///Pointer to the map of predecessors edges.
alpar@780
    58
    PredMap *predecessor;
alpar@802
    59
    ///Indicates if \ref predecessor is locally allocated (\c true) or not.
alpar@780
    60
    bool local_predecessor;
alpar@802
    61
    ///Pointer to the map of predecessors nodes.
alpar@780
    62
    PredNodeMap *pred_node;
alpar@802
    63
    ///Indicates if \ref pred_node is locally allocated (\c true) or not.
alpar@780
    64
    bool local_pred_node;
alpar@802
    65
    ///Pointer to the map of distances.
alpar@780
    66
    DistMap *distance;
alpar@802
    67
    ///Indicates if \ref distance is locally allocated (\c true) or not.
alpar@780
    68
    bool local_distance;
alpar@780
    69
alpar@802
    70
    ///The source node of the last execution.
alpar@780
    71
    Node source;
alpar@780
    72
alpar@780
    73
alpar@781
    74
    ///Initializes the maps.
alpar@780
    75
    void init_maps() 
alpar@780
    76
    {
alpar@780
    77
      if(!predecessor) {
alpar@780
    78
	local_predecessor = true;
alpar@780
    79
	predecessor = new PredMap(*G);
alpar@780
    80
      }
alpar@780
    81
      if(!pred_node) {
alpar@780
    82
	local_pred_node = true;
alpar@780
    83
	pred_node = new PredNodeMap(*G);
alpar@780
    84
      }
alpar@780
    85
      if(!distance) {
alpar@780
    86
	local_distance = true;
alpar@780
    87
	distance = new DistMap(*G);
alpar@780
    88
      }
alpar@780
    89
    }
alpar@780
    90
    
alpar@780
    91
  public :    
alpar@802
    92
    ///Constructor.
alpar@802
    93
    
alpar@802
    94
    ///\param _G the graph the algorithm will run on.
alpar@780
    95
    Dfs(const Graph& _G) :
alpar@780
    96
      G(&_G),
alpar@780
    97
      predecessor(NULL), local_predecessor(false),
alpar@780
    98
      pred_node(NULL), local_pred_node(false),
alpar@780
    99
      distance(NULL), local_distance(false)
alpar@780
   100
    { }
alpar@780
   101
    
alpar@802
   102
    ///Destructor.
alpar@780
   103
    ~Dfs() 
alpar@780
   104
    {
alpar@780
   105
      if(local_predecessor) delete predecessor;
alpar@780
   106
      if(local_pred_node) delete pred_node;
alpar@780
   107
      if(local_distance) delete distance;
alpar@780
   108
    }
alpar@780
   109
alpar@780
   110
    ///Sets the map storing the predecessor edges.
alpar@780
   111
alpar@780
   112
    ///Sets the map storing the predecessor edges.
alpar@780
   113
    ///If you don't use this function before calling \ref run(),
alpar@780
   114
    ///it will allocate one. The destuctor deallocates this
alpar@780
   115
    ///automatically allocated map, of course.
alpar@780
   116
    ///\return <tt> (*this) </tt>
alpar@780
   117
    Dfs &setPredMap(PredMap &m) 
alpar@780
   118
    {
alpar@780
   119
      if(local_predecessor) {
alpar@780
   120
	delete predecessor;
alpar@780
   121
	local_predecessor=false;
alpar@780
   122
      }
alpar@780
   123
      predecessor = &m;
alpar@780
   124
      return *this;
alpar@780
   125
    }
alpar@780
   126
alpar@780
   127
    ///Sets the map storing the predecessor nodes.
alpar@780
   128
alpar@780
   129
    ///Sets the map storing the predecessor nodes.
alpar@780
   130
    ///If you don't use this function before calling \ref run(),
alpar@780
   131
    ///it will allocate one. The destuctor deallocates this
alpar@780
   132
    ///automatically allocated map, of course.
alpar@780
   133
    ///\return <tt> (*this) </tt>
alpar@780
   134
    Dfs &setPredNodeMap(PredNodeMap &m) 
alpar@780
   135
    {
alpar@780
   136
      if(local_pred_node) {
alpar@780
   137
	delete pred_node;
alpar@780
   138
	local_pred_node=false;
alpar@780
   139
      }
alpar@780
   140
      pred_node = &m;
alpar@780
   141
      return *this;
alpar@780
   142
    }
alpar@780
   143
alpar@780
   144
    ///Sets the map storing the distances calculated by the algorithm.
alpar@780
   145
alpar@780
   146
    ///Sets the map storing the distances calculated by the algorithm.
alpar@780
   147
    ///If you don't use this function before calling \ref run(),
alpar@780
   148
    ///it will allocate one. The destuctor deallocates this
alpar@780
   149
    ///automatically allocated map, of course.
alpar@780
   150
    ///\return <tt> (*this) </tt>
alpar@780
   151
    Dfs &setDistMap(DistMap &m) 
alpar@780
   152
    {
alpar@780
   153
      if(local_distance) {
alpar@780
   154
	delete distance;
alpar@780
   155
	local_distance=false;
alpar@780
   156
      }
alpar@780
   157
      distance = &m;
alpar@780
   158
      return *this;
alpar@780
   159
    }
alpar@780
   160
    
alpar@780
   161
  ///Runs %DFS algorithm from node \c s.
alpar@780
   162
alpar@780
   163
  ///This method runs the %DFS algorithm from a root node \c s
alpar@780
   164
  ///in order to
alpar@781
   165
  ///compute 
alpar@781
   166
  ///- a %DFS tree and
alpar@781
   167
  ///- the distance of each node from the root on this tree.
alpar@780
   168
 
alpar@780
   169
    void run(Node s) {
alpar@780
   170
      
alpar@780
   171
      init_maps();
alpar@780
   172
      
alpar@780
   173
      source = s;
alpar@780
   174
      
alpar@780
   175
      for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
alpar@780
   176
	predecessor->set(u,INVALID);
alpar@780
   177
	pred_node->set(u,INVALID);
alpar@780
   178
      }
alpar@780
   179
      
alpar@780
   180
      int N=G->nodeNum();
alpar@780
   181
      std::vector<typename Graph::OutEdgeIt> Q(N);
alpar@780
   182
alpar@780
   183
      int Qh=0;
alpar@780
   184
      
alpar@780
   185
      G->first(Q[Qh],s);
alpar@780
   186
      distance->set(s, 0);
alpar@780
   187
alpar@780
   188
      Node n=s;
alpar@780
   189
      Node m;
alpar@780
   190
      OutEdgeIt e;
alpar@780
   191
      do {
alpar@780
   192
	if((e=Q[Qh])!=INVALID)
alpar@780
   193
	  if((m=G->head(e))!=s && (*predecessor)[m=G->head(e)]==INVALID) {
alpar@780
   194
	    predecessor->set(m,e);
alpar@780
   195
	    pred_node->set(m,n);
alpar@780
   196
	    G->first(Q[++Qh],m);
alpar@780
   197
	    distance->set(m,Qh);
alpar@780
   198
	    n=m;
alpar@780
   199
	  }
alpar@780
   200
	  else ++Q[Qh];
alpar@780
   201
	else if(--Qh>=0) n=G->tail(Q[Qh]);
alpar@780
   202
      } while(Qh>=0);
alpar@780
   203
    }
alpar@780
   204
    
alpar@781
   205
    ///The distance of a node from the root on the %DFS tree.
alpar@780
   206
alpar@781
   207
    ///Returns the distance of a node from the root on the %DFS tree.
alpar@780
   208
    ///\pre \ref run() must be called before using this function.
alpar@780
   209
    ///\warning If node \c v in unreachable from the root the return value
alpar@780
   210
    ///of this funcion is undefined.
alpar@780
   211
    int dist(Node v) const { return (*distance)[v]; }
alpar@780
   212
alpar@781
   213
    ///Returns the 'previous edge' of the %DFS path tree.
alpar@780
   214
alpar@781
   215
    ///For a node \c v it returns the last edge of the path on the %DFS tree
alpar@781
   216
    ///from the root to \c
alpar@780
   217
    ///v. It is \ref INVALID
alpar@780
   218
    ///if \c v is unreachable from the root or if \c v=s. The
alpar@781
   219
    ///%DFS tree used here is equal to the %DFS tree used in
alpar@780
   220
    ///\ref predNode(Node v).  \pre \ref run() must be called before using
alpar@780
   221
    ///this function.
alpar@780
   222
    Edge pred(Node v) const { return (*predecessor)[v]; }
alpar@780
   223
alpar@781
   224
    ///Returns the 'previous node' of the %DFS tree.
alpar@780
   225
alpar@781
   226
    ///For a node \c v it returns the 'previous node' on the %DFS tree,
alpar@781
   227
    ///i.e. it returns the last but one node of the path from the
alpar@781
   228
    ///root to \c /v on the %DFS tree.
alpar@781
   229
    ///It is INVALID if \c v is unreachable from the root or if
alpar@781
   230
    ///\c v=s.
alpar@781
   231
    ///\pre \ref run() must be called before
alpar@780
   232
    ///using this function.
alpar@780
   233
    Node predNode(Node v) const { return (*pred_node)[v]; }
alpar@780
   234
    
alpar@781
   235
    ///Returns a reference to the NodeMap of distances on the %DFS tree.
alpar@780
   236
    
alpar@781
   237
    ///Returns a reference to the NodeMap of distances on the %DFS tree.
alpar@781
   238
    ///\pre \ref run() must
alpar@780
   239
    ///be called before using this function.
alpar@780
   240
    const DistMap &distMap() const { return *distance;}
alpar@780
   241
 
alpar@781
   242
    ///Returns a reference to the %DFS tree map.
alpar@780
   243
alpar@780
   244
    ///Returns a reference to the NodeMap of the edges of the
alpar@781
   245
    ///%DFS tree.
alpar@780
   246
    ///\pre \ref run() must be called before using this function.
alpar@780
   247
    const PredMap &predMap() const { return *predecessor;}
alpar@780
   248
 
alpar@781
   249
    ///Returns a reference to the map of last but one nodes of the %DFS tree.
alpar@780
   250
alpar@781
   251
    ///Returns a reference to the NodeMap of the last but one nodes of the paths
alpar@781
   252
    ///on the
alpar@781
   253
    ///%DFS tree.
alpar@780
   254
    ///\pre \ref run() must be called before using this function.
alpar@780
   255
    const PredNodeMap &predNodeMap() const { return *pred_node;}
alpar@780
   256
alpar@780
   257
    ///Checks if a node is reachable from the root.
alpar@780
   258
alpar@780
   259
    ///Returns \c true if \c v is reachable from the root.
alpar@802
   260
    ///\note The root node is reported to be reached!
alpar@780
   261
    ///
alpar@780
   262
    ///\pre \ref run() must be called before using this function.
alpar@780
   263
    ///
alpar@780
   264
    bool reached(Node v) { return v==source || (*predecessor)[v]!=INVALID; }
alpar@780
   265
    
alpar@780
   266
  };
alpar@780
   267
  
alpar@780
   268
/// @}
alpar@780
   269
  
alpar@780
   270
} //END OF NAMESPACE HUGO
alpar@780
   271
alpar@780
   272
#endif
alpar@780
   273
alpar@780
   274