alpar@780: // -*- C++ -*- alpar@780: #ifndef HUGO_DFS_H alpar@780: #define HUGO_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: alpar@780: #include alpar@780: #include alpar@780: alpar@780: namespace hugo { 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@780: typedef typename Graph::Node Node; alpar@780: typedef typename Graph::NodeIt NodeIt; alpar@780: typedef typename Graph::Edge Edge; 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@780: const Graph *G; alpar@780: PredMap *predecessor; alpar@780: bool local_predecessor; alpar@780: PredNodeMap *pred_node; alpar@780: bool local_pred_node; alpar@780: DistMap *distance; alpar@780: bool local_distance; alpar@780: alpar@780: //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@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@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 graph the algorithm will run on. alpar@780: alpar@780: ///Sets the graph the algorithm will run on. alpar@780: ///\return (*this) alpar@781: ///\bug What about maps? alpar@781: ///\todo It may be unnecessary alpar@780: Dfs &setGraph(const Graph &_G) alpar@780: { alpar@780: G = &_G; alpar@780: return *this; 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: alpar@780: int N=G->nodeNum(); alpar@780: std::vector Q(N); alpar@780: alpar@780: int Qh=0; alpar@780: alpar@780: G->first(Q[Qh],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@780: if((m=G->head(e))!=s && (*predecessor)[m=G->head(e)]==INVALID) { alpar@780: predecessor->set(m,e); alpar@780: pred_node->set(m,n); alpar@780: G->first(Q[++Qh],m); alpar@780: distance->set(m,Qh); alpar@780: n=m; alpar@780: } alpar@780: else ++Q[Qh]; alpar@780: else if(--Qh>=0) n=G->tail(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@780: ///\warning 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@780: } //END OF NAMESPACE HUGO alpar@780: alpar@780: #endif alpar@780: alpar@780: