# HG changeset patch # User deba # Date 1130173382 0 # Node ID 4cade85793633fc14679b504bfbe42bc1922e221 # Parent b1385f5da81b81d8c775c70d1948d16d7105f549 Bug fix in connectedComponents Strongly connected components diff -r b1385f5da81b -r 4cade8579363 lemon/topology.h --- a/lemon/topology.h Mon Oct 24 15:59:38 2005 +0000 +++ b/lemon/topology.h Mon Oct 24 17:03:02 2005 +0000 @@ -18,6 +18,7 @@ #define LEMON_TOPOLOGY_H #include +#include #include #include @@ -220,19 +221,19 @@ /// ///\param g The graph. In must be undirected. ///\return The number of components - ///\todo Test required - template - int numberOfComponents(const UGraph &g) - { - int c=0; - Bfs bfs(g); + template + int countConnectedComponents(const UndirGraph &g) { + checkConcept(); + int c = 0; + Bfs bfs(g); bfs.init(); - for(typename Graph::NodeIt n(g);n!=INVALID;++n) + for(typename UndirGraph::NodeIt n(g); n != INVALID; ++n) { if(!bfs.reached(n)) { - c++; bfs.addSource(n); bfs.start(); + ++c; } + } return c; } @@ -248,23 +249,173 @@ ///set continuously. ///\return The number of components ///\todo Test required - template - int connectedComponents(const UGraph &g, WMap &comp) - { - int c=0; - Bfs bfs(g); + template + int connectedComponents(const UndirGraph &g, IntNodeMap &comp) { + checkConcept(); + checkConcept, + IntNodeMap>(); + int c = 0; + Bfs bfs(g); bfs.init(); - for(typename Graph::NodeIt n(g);n!=INVALID;++n) + for(typename UndirGraph::NodeIt n(g); n != INVALID; ++n) { if(!bfs.reached(n)) { bfs.addSource(n); - while ( bfs.nextNode()!=INVALID ) { - comp[bfs.nextNode()]=c; - processNextNode(); - c++; + while (!bfs.emptyQueue()) { + comp[bfs.nextNode()] = c; + bfs.processNextNode(); + } + ++c; } + } return c; } + namespace _components_bits { + + template + struct FillWriteMap : public MapBase { + public: + FillWriteMap(IntMap& _map, int& _comp) + : map(_map), comp(_comp) {} + void set(Key key, bool value) { + if (value) { map.set(key, comp); } + } + private: + IntMap& map; + int& comp; + }; + + template > + struct BackInserterWriteMap : public MapBase { + public: + BackInserterWriteMap(Container& _container) + : container(_container) {} + void set(Key key, bool value) { + if (value) { container.push_back(key); } + } + private: + Container& container; + }; + + } + + /// \brief Count the strongly connected components of a directed graph + /// + /// Count the strongly connected components of a directed graph + /// + /// \param g The graph. + /// \return The number of components + template + int countStronglyConnectedComponents(const Graph& graph) { + checkConcept(); + + using namespace _components_bits; + + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + + + typename Dfs:: + template DefProcessedMap >:: + Create dfs(graph); + + std::vector nodes; + BackInserterWriteMap processed(nodes); + dfs.processedMap(processed); + + dfs.init(); + for (NodeIt it(graph); it != INVALID; ++it) { + if (!dfs.reached(it)) { + dfs.addSource(it); + dfs.start(); + } + } + + typedef RevGraphAdaptor RGraph; + + RGraph rgraph(graph); + + Dfs rdfs(rgraph); + + int num = 0; + + rdfs.init(); + for (typename std::vector::reverse_iterator + it = nodes.rbegin(); it != nodes.rend(); ++it) { + if (!rdfs.reached(*it)) { + rdfs.addSource(*it); + rdfs.start(); + ++num; + } + } + return num; + } + + /// \brief Find the strongly connected components of a directed graph + /// + /// Find the strongly connected components of a directed graph + /// + /// \param g The graph. + /// \retval comp A writable node map. The values will be set from 0 to + /// the number of the strongly connected components minus one. Each values + /// of the map will be set exactly once, the values of a certain component + /// will be set continuously. + /// \return The number of components + template + int stronglyConnectedComponents(const Graph& graph, IntNodeMap& comp) { + checkConcept(); + checkConcept, IntNodeMap>(); + + using namespace _components_bits; + + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + + + typename Dfs:: + template DefProcessedMap >:: + Create dfs(graph); + + std::vector nodes; + BackInserterWriteMap processed(nodes); + dfs.processedMap(processed); + + dfs.init(); + for (NodeIt it(graph); it != INVALID; ++it) { + if (!dfs.reached(it)) { + dfs.addSource(it); + dfs.start(); + } + } + + typedef RevGraphAdaptor RGraph; + + RGraph rgraph(graph); + + typename Dfs:: + template DefProcessedMap >:: + Create rdfs(rgraph); + + int num = 0; + FillWriteMap rprocessed(comp, num); + rdfs.processedMap(rprocessed); + + rdfs.init(); + for (typename std::vector::reverse_iterator + it = nodes.rbegin(); it != nodes.rend(); ++it) { + if (!rdfs.reached(*it)) { + rdfs.addSource(*it); + rdfs.start(); + ++num; + } + } + return num; + } + } //namespace lemon #endif //LEMON_TOPOLOGY_H