alpar@906: /* -*- C++ -*- alpar@921: * src/lemon/dfs.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@1164: * Copyright (C) 2005 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_DFS_H alpar@921: #define LEMON_DFS_H alpar@780: alpar@780: ///\ingroup flowalgs alpar@780: ///\file alpar@781: ///\brief %DFS algorithm. alpar@780: /// alpar@780: ///\todo Revise Manual. alpar@780: klao@946: #include alpar@921: #include alpar@780: alpar@921: namespace lemon { alpar@780: alpar@780: /// \addtogroup flowalgs alpar@780: /// @{ alpar@780: alpar@781: ///%DFS algorithm class. alpar@780: alpar@781: ///This class provides an efficient implementation of %DFS algorithm. alpar@780: /// alpar@780: ///\param GR The graph type the algorithm runs on. alpar@780: /// alpar@781: ///\author Alpar Juttner alpar@780: alpar@780: #ifdef DOXYGEN alpar@780: template alpar@780: #else alpar@780: template alpar@780: #endif alpar@780: class Dfs{ alpar@780: public: alpar@780: ///The type of the underlying graph. alpar@780: typedef GR Graph; alpar@911: ///\e alpar@780: typedef typename Graph::Node Node; alpar@911: ///\e alpar@780: typedef typename Graph::NodeIt NodeIt; alpar@911: ///\e alpar@780: typedef typename Graph::Edge Edge; alpar@911: ///\e alpar@780: typedef typename Graph::OutEdgeIt OutEdgeIt; alpar@780: alpar@780: ///\brief The type of the map that stores the last alpar@781: ///edges of the paths on the %DFS tree. alpar@780: typedef typename Graph::template NodeMap PredMap; alpar@780: ///\brief The type of the map that stores the last but one alpar@781: ///nodes of the paths on the %DFS tree. alpar@780: typedef typename Graph::template NodeMap PredNodeMap; alpar@781: ///The type of the map that stores the dists of the nodes on the %DFS tree. alpar@780: typedef typename Graph::template NodeMap DistMap; alpar@780: alpar@780: private: alpar@802: /// Pointer to the underlying graph. alpar@780: const Graph *G; alpar@802: ///Pointer to the map of predecessors edges. alpar@780: PredMap *predecessor; alpar@802: ///Indicates if \ref predecessor is locally allocated (\c true) or not. alpar@780: bool local_predecessor; alpar@802: ///Pointer to the map of predecessors nodes. alpar@780: PredNodeMap *pred_node; alpar@802: ///Indicates if \ref pred_node is locally allocated (\c true) or not. alpar@780: bool local_pred_node; alpar@802: ///Pointer to the map of distances. alpar@780: DistMap *distance; alpar@802: ///Indicates if \ref distance is locally allocated (\c true) or not. alpar@780: bool local_distance; alpar@780: alpar@802: ///The source node of the last execution. alpar@780: Node source; alpar@780: alpar@780: alpar@781: ///Initializes the maps. alpar@780: void init_maps() alpar@780: { alpar@780: if(!predecessor) { alpar@780: local_predecessor = true; alpar@780: predecessor = new PredMap(*G); alpar@780: } alpar@780: if(!pred_node) { alpar@780: local_pred_node = true; alpar@780: pred_node = new PredNodeMap(*G); alpar@780: } alpar@780: if(!distance) { alpar@780: local_distance = true; alpar@780: distance = new DistMap(*G); alpar@780: } alpar@780: } alpar@780: alpar@780: public : alpar@802: ///Constructor. alpar@802: alpar@802: ///\param _G the graph the algorithm will run on. alpar@911: /// alpar@780: Dfs(const Graph& _G) : alpar@780: G(&_G), alpar@780: predecessor(NULL), local_predecessor(false), alpar@780: pred_node(NULL), local_pred_node(false), alpar@780: distance(NULL), local_distance(false) alpar@780: { } alpar@780: alpar@802: ///Destructor. alpar@780: ~Dfs() alpar@780: { alpar@780: if(local_predecessor) delete predecessor; alpar@780: if(local_pred_node) delete pred_node; alpar@780: if(local_distance) delete distance; alpar@780: } alpar@780: alpar@780: ///Sets the map storing the predecessor edges. alpar@780: alpar@780: ///Sets the map storing the predecessor edges. alpar@780: ///If you don't use this function before calling \ref run(), alpar@780: ///it will allocate one. The destuctor deallocates this alpar@780: ///automatically allocated map, of course. alpar@780: ///\return (*this) alpar@780: Dfs &setPredMap(PredMap &m) alpar@780: { alpar@780: if(local_predecessor) { alpar@780: delete predecessor; alpar@780: local_predecessor=false; alpar@780: } alpar@780: predecessor = &m; alpar@780: return *this; alpar@780: } alpar@780: alpar@780: ///Sets the map storing the predecessor nodes. alpar@780: alpar@780: ///Sets the map storing the predecessor nodes. alpar@780: ///If you don't use this function before calling \ref run(), alpar@780: ///it will allocate one. The destuctor deallocates this alpar@780: ///automatically allocated map, of course. alpar@780: ///\return (*this) alpar@780: Dfs &setPredNodeMap(PredNodeMap &m) alpar@780: { alpar@780: if(local_pred_node) { alpar@780: delete pred_node; alpar@780: local_pred_node=false; alpar@780: } alpar@780: pred_node = &m; alpar@780: return *this; alpar@780: } alpar@780: alpar@780: ///Sets the map storing the distances calculated by the algorithm. alpar@780: alpar@780: ///Sets the map storing the distances calculated by the algorithm. alpar@780: ///If you don't use this function before calling \ref run(), alpar@780: ///it will allocate one. The destuctor deallocates this alpar@780: ///automatically allocated map, of course. alpar@780: ///\return (*this) alpar@780: Dfs &setDistMap(DistMap &m) alpar@780: { alpar@780: if(local_distance) { alpar@780: delete distance; alpar@780: local_distance=false; alpar@780: } alpar@780: distance = &m; alpar@780: return *this; alpar@780: } alpar@780: alpar@780: ///Runs %DFS algorithm from node \c s. alpar@780: alpar@780: ///This method runs the %DFS algorithm from a root node \c s alpar@780: ///in order to alpar@781: ///compute alpar@781: ///- a %DFS tree and alpar@781: ///- the distance of each node from the root on this tree. alpar@780: alpar@780: void run(Node s) { alpar@780: alpar@780: init_maps(); alpar@780: alpar@780: source = s; alpar@780: alpar@780: for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { alpar@780: predecessor->set(u,INVALID); alpar@780: pred_node->set(u,INVALID); alpar@780: } alpar@780: klao@946: int N = countNodes(*G); alpar@780: std::vector Q(N); alpar@780: alpar@780: int Qh=0; alpar@780: klao@946: Q[Qh] = OutEdgeIt(*G, s); alpar@780: distance->set(s, 0); alpar@780: alpar@780: Node n=s; alpar@780: Node m; alpar@780: OutEdgeIt e; alpar@780: do { alpar@780: if((e=Q[Qh])!=INVALID) alpar@986: if((m=G->target(e))!=s && (*predecessor)[m=G->target(e)]==INVALID) { alpar@780: predecessor->set(m,e); alpar@780: pred_node->set(m,n); klao@946: Q[++Qh] = OutEdgeIt(*G, m); alpar@780: distance->set(m,Qh); alpar@780: n=m; alpar@780: } alpar@780: else ++Q[Qh]; alpar@986: else if(--Qh>=0) n=G->source(Q[Qh]); alpar@780: } while(Qh>=0); alpar@780: } alpar@780: alpar@781: ///The distance of a node from the root on the %DFS tree. alpar@780: alpar@781: ///Returns the distance of a node from the root on the %DFS tree. alpar@780: ///\pre \ref run() must be called before using this function. alpar@780: ///\warning If node \c v in unreachable from the root the return value alpar@780: ///of this funcion is undefined. alpar@780: int dist(Node v) const { return (*distance)[v]; } alpar@780: alpar@781: ///Returns the 'previous edge' of the %DFS path tree. alpar@780: alpar@781: ///For a node \c v it returns the last edge of the path on the %DFS tree alpar@781: ///from the root to \c alpar@780: ///v. It is \ref INVALID alpar@780: ///if \c v is unreachable from the root or if \c v=s. The alpar@781: ///%DFS tree used here is equal to the %DFS tree used in alpar@780: ///\ref predNode(Node v). \pre \ref run() must be called before using alpar@780: ///this function. alpar@780: Edge pred(Node v) const { return (*predecessor)[v]; } alpar@780: alpar@781: ///Returns the 'previous node' of the %DFS tree. alpar@780: alpar@781: ///For a node \c v it returns the 'previous node' on the %DFS tree, alpar@781: ///i.e. it returns the last but one node of the path from the alpar@781: ///root to \c /v on the %DFS tree. alpar@781: ///It is INVALID if \c v is unreachable from the root or if alpar@781: ///\c v=s. alpar@781: ///\pre \ref run() must be called before alpar@780: ///using this function. alpar@780: Node predNode(Node v) const { return (*pred_node)[v]; } alpar@780: alpar@781: ///Returns a reference to the NodeMap of distances on the %DFS tree. alpar@780: alpar@781: ///Returns a reference to the NodeMap of distances on the %DFS tree. alpar@781: ///\pre \ref run() must alpar@780: ///be called before using this function. alpar@780: const DistMap &distMap() const { return *distance;} alpar@780: alpar@781: ///Returns a reference to the %DFS tree map. alpar@780: alpar@780: ///Returns a reference to the NodeMap of the edges of the alpar@781: ///%DFS tree. alpar@780: ///\pre \ref run() must be called before using this function. alpar@780: const PredMap &predMap() const { return *predecessor;} alpar@780: alpar@781: ///Returns a reference to the map of last but one nodes of the %DFS tree. alpar@780: alpar@781: ///Returns a reference to the NodeMap of the last but one nodes of the paths alpar@781: ///on the alpar@781: ///%DFS tree. alpar@780: ///\pre \ref run() must be called before using this function. alpar@780: const PredNodeMap &predNodeMap() const { return *pred_node;} alpar@780: alpar@780: ///Checks if a node is reachable from the root. alpar@780: alpar@780: ///Returns \c true if \c v is reachable from the root. alpar@802: ///\note The root node is reported to be reached! alpar@780: /// alpar@780: ///\pre \ref run() must be called before using this function. alpar@780: /// alpar@780: bool reached(Node v) { return v==source || (*predecessor)[v]!=INVALID; } alpar@780: alpar@780: }; alpar@780: alpar@780: /// @} alpar@780: alpar@921: } //END OF NAMESPACE LEMON alpar@780: alpar@780: #endif alpar@780: alpar@780: