src/hugo/dfs.h
author alpar
Thu, 02 Sep 2004 17:11:04 +0000
changeset 790 2b9a43c0d64e
parent 780 e06d0d16595f
child 802 bc0c74eeb151
permissions -rw-r--r--
- 'minlengpaths_test.cc' added.
- Path tests in 'minlengpaths_test.cc' are swithced out.
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@780
    36
    typedef typename Graph::Node Node;
alpar@780
    37
    typedef typename Graph::NodeIt NodeIt;
alpar@780
    38
    typedef typename Graph::Edge Edge;
alpar@780
    39
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@780
    40
    
alpar@780
    41
    ///\brief The type of the map that stores the last
alpar@781
    42
    ///edges of the paths on the %DFS tree.
alpar@780
    43
    typedef typename Graph::template NodeMap<Edge> PredMap;
alpar@780
    44
    ///\brief The type of the map that stores the last but one
alpar@781
    45
    ///nodes of the paths on the %DFS tree.
alpar@780
    46
    typedef typename Graph::template NodeMap<Node> PredNodeMap;
alpar@781
    47
    ///The type of the map that stores the dists of the nodes on the %DFS tree.
alpar@780
    48
    typedef typename Graph::template NodeMap<int> DistMap;
alpar@780
    49
alpar@780
    50
  private:
alpar@780
    51
    const Graph *G;
alpar@780
    52
    PredMap *predecessor;
alpar@780
    53
    bool local_predecessor;
alpar@780
    54
    PredNodeMap *pred_node;
alpar@780
    55
    bool local_pred_node;
alpar@780
    56
    DistMap *distance;
alpar@780
    57
    bool local_distance;
alpar@780
    58
alpar@780
    59
    //The source node of the last execution.
alpar@780
    60
    Node source;
alpar@780
    61
alpar@780
    62
alpar@781
    63
    ///Initializes the maps.
alpar@780
    64
    void init_maps() 
alpar@780
    65
    {
alpar@780
    66
      if(!predecessor) {
alpar@780
    67
	local_predecessor = true;
alpar@780
    68
	predecessor = new PredMap(*G);
alpar@780
    69
      }
alpar@780
    70
      if(!pred_node) {
alpar@780
    71
	local_pred_node = true;
alpar@780
    72
	pred_node = new PredNodeMap(*G);
alpar@780
    73
      }
alpar@780
    74
      if(!distance) {
alpar@780
    75
	local_distance = true;
alpar@780
    76
	distance = new DistMap(*G);
alpar@780
    77
      }
alpar@780
    78
    }
alpar@780
    79
    
alpar@780
    80
  public :    
alpar@780
    81
    Dfs(const Graph& _G) :
alpar@780
    82
      G(&_G),
alpar@780
    83
      predecessor(NULL), local_predecessor(false),
alpar@780
    84
      pred_node(NULL), local_pred_node(false),
alpar@780
    85
      distance(NULL), local_distance(false)
alpar@780
    86
    { }
alpar@780
    87
    
alpar@780
    88
    ~Dfs() 
alpar@780
    89
    {
alpar@780
    90
      if(local_predecessor) delete predecessor;
alpar@780
    91
      if(local_pred_node) delete pred_node;
alpar@780
    92
      if(local_distance) delete distance;
alpar@780
    93
    }
alpar@780
    94
alpar@780
    95
    ///Sets the graph the algorithm will run on.
alpar@780
    96
alpar@780
    97
    ///Sets the graph the algorithm will run on.
alpar@780
    98
    ///\return <tt> (*this) </tt>
alpar@781
    99
    ///\bug What about maps?
alpar@781
   100
    ///\todo It may be unnecessary
alpar@780
   101
    Dfs &setGraph(const Graph &_G) 
alpar@780
   102
    {
alpar@780
   103
      G = &_G;
alpar@780
   104
      return *this;
alpar@780
   105
    }
alpar@780
   106
    ///Sets the map storing the predecessor edges.
alpar@780
   107
alpar@780
   108
    ///Sets the map storing the predecessor edges.
alpar@780
   109
    ///If you don't use this function before calling \ref run(),
alpar@780
   110
    ///it will allocate one. The destuctor deallocates this
alpar@780
   111
    ///automatically allocated map, of course.
alpar@780
   112
    ///\return <tt> (*this) </tt>
alpar@780
   113
    Dfs &setPredMap(PredMap &m) 
alpar@780
   114
    {
alpar@780
   115
      if(local_predecessor) {
alpar@780
   116
	delete predecessor;
alpar@780
   117
	local_predecessor=false;
alpar@780
   118
      }
alpar@780
   119
      predecessor = &m;
alpar@780
   120
      return *this;
alpar@780
   121
    }
alpar@780
   122
alpar@780
   123
    ///Sets the map storing the predecessor nodes.
alpar@780
   124
alpar@780
   125
    ///Sets the map storing the predecessor nodes.
alpar@780
   126
    ///If you don't use this function before calling \ref run(),
alpar@780
   127
    ///it will allocate one. The destuctor deallocates this
alpar@780
   128
    ///automatically allocated map, of course.
alpar@780
   129
    ///\return <tt> (*this) </tt>
alpar@780
   130
    Dfs &setPredNodeMap(PredNodeMap &m) 
alpar@780
   131
    {
alpar@780
   132
      if(local_pred_node) {
alpar@780
   133
	delete pred_node;
alpar@780
   134
	local_pred_node=false;
alpar@780
   135
      }
alpar@780
   136
      pred_node = &m;
alpar@780
   137
      return *this;
alpar@780
   138
    }
alpar@780
   139
alpar@780
   140
    ///Sets the map storing the distances calculated by the algorithm.
alpar@780
   141
alpar@780
   142
    ///Sets the map storing the distances calculated by the algorithm.
alpar@780
   143
    ///If you don't use this function before calling \ref run(),
alpar@780
   144
    ///it will allocate one. The destuctor deallocates this
alpar@780
   145
    ///automatically allocated map, of course.
alpar@780
   146
    ///\return <tt> (*this) </tt>
alpar@780
   147
    Dfs &setDistMap(DistMap &m) 
alpar@780
   148
    {
alpar@780
   149
      if(local_distance) {
alpar@780
   150
	delete distance;
alpar@780
   151
	local_distance=false;
alpar@780
   152
      }
alpar@780
   153
      distance = &m;
alpar@780
   154
      return *this;
alpar@780
   155
    }
alpar@780
   156
    
alpar@780
   157
  ///Runs %DFS algorithm from node \c s.
alpar@780
   158
alpar@780
   159
  ///This method runs the %DFS algorithm from a root node \c s
alpar@780
   160
  ///in order to
alpar@781
   161
  ///compute 
alpar@781
   162
  ///- a %DFS tree and
alpar@781
   163
  ///- the distance of each node from the root on this tree.
alpar@780
   164
 
alpar@780
   165
    void run(Node s) {
alpar@780
   166
      
alpar@780
   167
      init_maps();
alpar@780
   168
      
alpar@780
   169
      source = s;
alpar@780
   170
      
alpar@780
   171
      for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
alpar@780
   172
	predecessor->set(u,INVALID);
alpar@780
   173
	pred_node->set(u,INVALID);
alpar@780
   174
      }
alpar@780
   175
      
alpar@780
   176
      int N=G->nodeNum();
alpar@780
   177
      std::vector<typename Graph::OutEdgeIt> Q(N);
alpar@780
   178
alpar@780
   179
      int Qh=0;
alpar@780
   180
      
alpar@780
   181
      G->first(Q[Qh],s);
alpar@780
   182
      distance->set(s, 0);
alpar@780
   183
alpar@780
   184
      Node n=s;
alpar@780
   185
      Node m;
alpar@780
   186
      OutEdgeIt e;
alpar@780
   187
      do {
alpar@780
   188
	if((e=Q[Qh])!=INVALID)
alpar@780
   189
	  if((m=G->head(e))!=s && (*predecessor)[m=G->head(e)]==INVALID) {
alpar@780
   190
	    predecessor->set(m,e);
alpar@780
   191
	    pred_node->set(m,n);
alpar@780
   192
	    G->first(Q[++Qh],m);
alpar@780
   193
	    distance->set(m,Qh);
alpar@780
   194
	    n=m;
alpar@780
   195
	  }
alpar@780
   196
	  else ++Q[Qh];
alpar@780
   197
	else if(--Qh>=0) n=G->tail(Q[Qh]);
alpar@780
   198
      } while(Qh>=0);
alpar@780
   199
    }
alpar@780
   200
    
alpar@781
   201
    ///The distance of a node from the root on the %DFS tree.
alpar@780
   202
alpar@781
   203
    ///Returns the distance of a node from the root on the %DFS tree.
alpar@780
   204
    ///\pre \ref run() must be called before using this function.
alpar@780
   205
    ///\warning If node \c v in unreachable from the root the return value
alpar@780
   206
    ///of this funcion is undefined.
alpar@780
   207
    int dist(Node v) const { return (*distance)[v]; }
alpar@780
   208
alpar@781
   209
    ///Returns the 'previous edge' of the %DFS path tree.
alpar@780
   210
alpar@781
   211
    ///For a node \c v it returns the last edge of the path on the %DFS tree
alpar@781
   212
    ///from the root to \c
alpar@780
   213
    ///v. It is \ref INVALID
alpar@780
   214
    ///if \c v is unreachable from the root or if \c v=s. The
alpar@781
   215
    ///%DFS tree used here is equal to the %DFS tree used in
alpar@780
   216
    ///\ref predNode(Node v).  \pre \ref run() must be called before using
alpar@780
   217
    ///this function.
alpar@780
   218
    Edge pred(Node v) const { return (*predecessor)[v]; }
alpar@780
   219
alpar@781
   220
    ///Returns the 'previous node' of the %DFS tree.
alpar@780
   221
alpar@781
   222
    ///For a node \c v it returns the 'previous node' on the %DFS tree,
alpar@781
   223
    ///i.e. it returns the last but one node of the path from the
alpar@781
   224
    ///root to \c /v on the %DFS tree.
alpar@781
   225
    ///It is INVALID if \c v is unreachable from the root or if
alpar@781
   226
    ///\c v=s.
alpar@781
   227
    ///\pre \ref run() must be called before
alpar@780
   228
    ///using this function.
alpar@780
   229
    Node predNode(Node v) const { return (*pred_node)[v]; }
alpar@780
   230
    
alpar@781
   231
    ///Returns a reference to the NodeMap of distances on the %DFS tree.
alpar@780
   232
    
alpar@781
   233
    ///Returns a reference to the NodeMap of distances on the %DFS tree.
alpar@781
   234
    ///\pre \ref run() must
alpar@780
   235
    ///be called before using this function.
alpar@780
   236
    const DistMap &distMap() const { return *distance;}
alpar@780
   237
 
alpar@781
   238
    ///Returns a reference to the %DFS tree map.
alpar@780
   239
alpar@780
   240
    ///Returns a reference to the NodeMap of the edges of the
alpar@781
   241
    ///%DFS tree.
alpar@780
   242
    ///\pre \ref run() must be called before using this function.
alpar@780
   243
    const PredMap &predMap() const { return *predecessor;}
alpar@780
   244
 
alpar@781
   245
    ///Returns a reference to the map of last but one nodes of the %DFS tree.
alpar@780
   246
alpar@781
   247
    ///Returns a reference to the NodeMap of the last but one nodes of the paths
alpar@781
   248
    ///on the
alpar@781
   249
    ///%DFS tree.
alpar@780
   250
    ///\pre \ref run() must be called before using this function.
alpar@780
   251
    const PredNodeMap &predNodeMap() const { return *pred_node;}
alpar@780
   252
alpar@780
   253
    ///Checks if a node is reachable from the root.
alpar@780
   254
alpar@780
   255
    ///Returns \c true if \c v is reachable from the root.
alpar@780
   256
    ///\warning The root node is reported to be reached!
alpar@780
   257
    ///
alpar@780
   258
    ///\pre \ref run() must be called before using this function.
alpar@780
   259
    ///
alpar@780
   260
    bool reached(Node v) { return v==source || (*predecessor)[v]!=INVALID; }
alpar@780
   261
    
alpar@780
   262
  };
alpar@780
   263
  
alpar@780
   264
/// @}
alpar@780
   265
  
alpar@780
   266
} //END OF NAMESPACE HUGO
alpar@780
   267
alpar@780
   268
#endif
alpar@780
   269
alpar@780
   270