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