alpar@906: /* -*- C++ -*- alpar@921: * src/lemon/bfs.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@906: * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@906: * (Egervary Combinatorial Optimization Research Group, EGRES). alpar@906: * alpar@906: * Permission to use, modify and distribute this software is granted alpar@906: * provided that this copyright notice appears in all copies. For alpar@906: * precise terms see the accompanying LICENSE file. alpar@906: * alpar@906: * This software is provided "AS IS" with no warranty of any kind, alpar@906: * express or implied, and with no claim as to its suitability for any alpar@906: * purpose. alpar@906: * alpar@906: */ alpar@906: alpar@921: #ifndef LEMON_BFS_H alpar@921: #define LEMON_BFS_H alpar@774: alpar@774: ///\ingroup flowalgs alpar@774: ///\file alpar@774: ///\brief Bfs algorithm. alpar@774: /// alpar@774: ///\todo Revise Manual. alpar@774: alpar@921: #include alpar@921: #include klao@977: #include alpar@774: alpar@921: namespace lemon { alpar@774: alpar@774: /// \addtogroup flowalgs alpar@774: /// @{ alpar@774: alpar@781: ///%BFS algorithm class. alpar@774: alpar@781: ///This class provides an efficient implementation of %BFS algorithm. alpar@781: ///\param GR The graph type the algorithm runs on. alpar@781: ///This class does the same as Dijkstra does with constant 1 edge length, alpar@781: ///but it is faster. alpar@774: /// alpar@781: ///\author Alpar Juttner alpar@774: alpar@774: #ifdef DOXYGEN alpar@774: template alpar@774: #else alpar@774: template alpar@774: #endif alpar@774: class Bfs{ alpar@774: public: alpar@774: ///The type of the underlying graph. alpar@774: typedef GR Graph; alpar@911: ///\e alpar@774: typedef typename Graph::Node Node; alpar@911: ///\e alpar@774: typedef typename Graph::NodeIt NodeIt; alpar@911: ///\e alpar@774: typedef typename Graph::Edge Edge; alpar@911: ///\e alpar@774: typedef typename Graph::OutEdgeIt OutEdgeIt; alpar@774: alpar@774: ///\brief The type of the map that stores the last alpar@774: ///edges of the shortest paths. alpar@774: typedef typename Graph::template NodeMap PredMap; alpar@774: ///\brief The type of the map that stores the last but one alpar@774: ///nodes of the shortest paths. alpar@774: typedef typename Graph::template NodeMap PredNodeMap; alpar@774: ///The type of the map that stores the dists of the nodes. alpar@774: typedef typename Graph::template NodeMap DistMap; alpar@774: alpar@774: private: alpar@802: /// Pointer to the underlying graph. alpar@774: const Graph *G; alpar@802: ///Pointer to the map of predecessors edges. alpar@774: PredMap *predecessor; alpar@802: ///Indicates if \ref predecessor is locally allocated (\c true) or not. alpar@774: bool local_predecessor; alpar@802: ///Pointer to the map of predecessors nodes. alpar@774: PredNodeMap *pred_node; alpar@802: ///Indicates if \ref pred_node is locally allocated (\c true) or not. alpar@774: bool local_pred_node; alpar@802: ///Pointer to the map of distances. alpar@774: DistMap *distance; alpar@802: ///Indicates if \ref distance is locally allocated (\c true) or not. alpar@774: bool local_distance; alpar@774: alpar@802: ///The source node of the last execution. alpar@774: Node source; alpar@774: alpar@774: alpar@781: ///Initializes the maps. alpar@774: void init_maps() alpar@774: { alpar@774: if(!predecessor) { alpar@774: local_predecessor = true; alpar@774: predecessor = new PredMap(*G); alpar@774: } alpar@774: if(!pred_node) { alpar@774: local_pred_node = true; alpar@774: pred_node = new PredNodeMap(*G); alpar@774: } alpar@774: if(!distance) { alpar@774: local_distance = true; alpar@774: distance = new DistMap(*G); alpar@774: } alpar@774: } alpar@774: alpar@774: public : alpar@802: ///Constructor. alpar@802: alpar@802: ///\param _G the graph the algorithm will run on. alpar@911: /// alpar@774: Bfs(const Graph& _G) : alpar@774: G(&_G), alpar@774: predecessor(NULL), local_predecessor(false), alpar@774: pred_node(NULL), local_pred_node(false), alpar@774: distance(NULL), local_distance(false) alpar@774: { } alpar@774: alpar@802: ///Destructor. alpar@774: ~Bfs() alpar@774: { alpar@774: if(local_predecessor) delete predecessor; alpar@774: if(local_pred_node) delete pred_node; alpar@774: if(local_distance) delete distance; alpar@774: } alpar@774: alpar@774: ///Sets the map storing the predecessor edges. alpar@774: alpar@774: ///Sets the map storing the predecessor edges. alpar@774: ///If you don't use this function before calling \ref run(), alpar@774: ///it will allocate one. The destuctor deallocates this alpar@774: ///automatically allocated map, of course. alpar@774: ///\return (*this) alpar@774: Bfs &setPredMap(PredMap &m) alpar@774: { alpar@774: if(local_predecessor) { alpar@774: delete predecessor; alpar@774: local_predecessor=false; alpar@774: } alpar@774: predecessor = &m; alpar@774: return *this; alpar@774: } alpar@774: alpar@774: ///Sets the map storing the predecessor nodes. alpar@774: alpar@774: ///Sets the map storing the predecessor nodes. alpar@774: ///If you don't use this function before calling \ref run(), alpar@774: ///it will allocate one. The destuctor deallocates this alpar@774: ///automatically allocated map, of course. alpar@774: ///\return (*this) alpar@774: Bfs &setPredNodeMap(PredNodeMap &m) alpar@774: { alpar@774: if(local_pred_node) { alpar@774: delete pred_node; alpar@774: local_pred_node=false; alpar@774: } alpar@774: pred_node = &m; alpar@774: return *this; alpar@774: } alpar@774: alpar@774: ///Sets the map storing the distances calculated by the algorithm. alpar@774: alpar@774: ///Sets the map storing the distances calculated by the algorithm. alpar@774: ///If you don't use this function before calling \ref run(), alpar@774: ///it will allocate one. The destuctor deallocates this alpar@774: ///automatically allocated map, of course. alpar@774: ///\return (*this) alpar@774: Bfs &setDistMap(DistMap &m) alpar@774: { alpar@774: if(local_distance) { alpar@774: delete distance; alpar@774: local_distance=false; alpar@774: } alpar@774: distance = &m; alpar@774: return *this; alpar@774: } alpar@774: alpar@774: ///Runs %BFS algorithm from node \c s. alpar@774: alpar@774: ///This method runs the %BFS algorithm from a root node \c s alpar@774: ///in order to alpar@781: ///compute a alpar@774: ///shortest path to each node. The algorithm computes alpar@781: ///- The %BFS tree. alpar@774: ///- The distance of each node from the root. alpar@774: alpar@774: void run(Node s) { alpar@774: alpar@774: init_maps(); alpar@774: alpar@774: source = s; alpar@774: alpar@774: for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { alpar@774: predecessor->set(u,INVALID); alpar@774: pred_node->set(u,INVALID); alpar@774: } alpar@774: klao@946: int N = countNodes(*G); alpar@774: std::vector Q(N); alpar@774: int Qh=0; alpar@774: int Qt=0; alpar@774: alpar@774: Q[Qh++]=source; alpar@774: distance->set(s, 0); alpar@774: do { alpar@774: Node m; alpar@774: Node n=Q[Qt++]; alpar@774: int d= (*distance)[n]+1; alpar@774: alpar@774: for(OutEdgeIt e(*G,n);e!=INVALID;++e) alpar@986: if((m=G->target(e))!=s && (*predecessor)[m]==INVALID) { alpar@774: Q[Qh++]=m; alpar@774: predecessor->set(m,e); alpar@774: pred_node->set(m,n); alpar@774: distance->set(m,d); alpar@774: } alpar@774: } while(Qt!=Qh); alpar@774: } alpar@774: alpar@774: ///The distance of a node from the root. alpar@774: alpar@774: ///Returns the distance of a node from the root. alpar@774: ///\pre \ref run() must be called before using this function. alpar@774: ///\warning If node \c v in unreachable from the root the return value alpar@774: ///of this funcion is undefined. alpar@774: int dist(Node v) const { return (*distance)[v]; } alpar@774: alpar@781: ///Returns the 'previous edge' of the %BFS path tree. alpar@774: alpar@781: ///For a node \c v it returns the 'previous edge' of the %BFS tree, alpar@781: ///i.e. it returns the last edge of a shortest path from the root to \c alpar@774: ///v. It is \ref INVALID alpar@774: ///if \c v is unreachable from the root or if \c v=s. The alpar@781: ///%BFS tree used here is equal to the %BFS tree used in alpar@774: ///\ref predNode(Node v). \pre \ref run() must be called before using alpar@774: ///this function. alpar@774: Edge pred(Node v) const { return (*predecessor)[v]; } alpar@774: alpar@781: ///Returns the 'previous node' of the %BFS tree. alpar@774: alpar@781: ///For a node \c v it returns the 'previous node' on the %BFS tree, alpar@774: ///i.e. it returns the last but one node from a shortest path from the alpar@774: ///root to \c /v. It is INVALID if \c v is unreachable from the root or if alpar@781: ///\c v=s. The shortest path tree used here is equal to the %BFS alpar@774: ///tree used in \ref pred(Node v). \pre \ref run() must be called before alpar@774: ///using this function. alpar@774: Node predNode(Node v) const { return (*pred_node)[v]; } alpar@774: alpar@774: ///Returns a reference to the NodeMap of distances. alpar@774: alpar@774: ///Returns a reference to the NodeMap of distances. \pre \ref run() must alpar@774: ///be called before using this function. alpar@774: const DistMap &distMap() const { return *distance;} alpar@774: alpar@781: ///Returns a reference to the %BFS tree map. alpar@774: alpar@774: ///Returns a reference to the NodeMap of the edges of the alpar@781: ///%BFS tree. alpar@774: ///\pre \ref run() must be called before using this function. alpar@774: const PredMap &predMap() const { return *predecessor;} alpar@774: alpar@781: ///Returns a reference to the map of last but one nodes of shortest paths. alpar@774: alpar@781: ///Returns a reference to the NodeMap of the last but one nodes on the alpar@781: ///%BFS tree. alpar@774: ///\pre \ref run() must be called before using this function. alpar@774: const PredNodeMap &predNodeMap() const { return *pred_node;} alpar@774: alpar@774: ///Checks if a node is reachable from the root. alpar@774: alpar@774: ///Returns \c true if \c v is reachable from the root. alpar@802: ///\note The root node is reported to be reached! alpar@774: /// alpar@774: ///\pre \ref run() must be called before using this function. alpar@774: /// alpar@780: bool reached(Node v) { return v==source || (*predecessor)[v]!=INVALID; } alpar@774: alpar@774: }; alpar@774: alpar@774: /// @} alpar@774: alpar@921: } //END OF NAMESPACE LEMON alpar@774: alpar@774: #endif alpar@774: alpar@774: