[Lemon-commits] [lemon_svn] deba: r2279 - in hugo/trunk: doc lemon
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:51:28 CET 2006
Author: deba
Date: Wed Nov 2 16:23:46 2005
New Revision: 2279
Modified:
hugo/trunk/doc/groups.dox
hugo/trunk/lemon/topology.h
Log:
Connected components, etc...
Based on the dfs visitor interface
Modified: hugo/trunk/doc/groups.dox
==============================================================================
--- hugo/trunk/doc/groups.dox (original)
+++ hugo/trunk/doc/groups.dox Wed Nov 2 16:23:46 2005
@@ -125,6 +125,13 @@
*/
/**
+ at defgroup topology Topology related algorithms
+ at ingroup galgs
+\brief This group describes the algorithms
+for discover the topology of the graphs.
+*/
+
+/**
@defgroup exceptions Exceptions
This group contains the exceptions thrown by LEMON library
*/
Modified: hugo/trunk/lemon/topology.h
==============================================================================
--- hugo/trunk/lemon/topology.h (original)
+++ hugo/trunk/lemon/topology.h Wed Nov 2 16:23:46 2005
@@ -20,49 +20,1208 @@
#include <lemon/dfs.h>
#include <lemon/bfs.h>
#include <lemon/graph_utils.h>
+#include <lemon/graph_adaptor.h>
+#include <lemon/maps.h>
#include <lemon/concept/graph.h>
#include <lemon/concept/undir_graph.h>
#include <lemon/concept_check.h>
-/// \ingroup flowalgs
+#include <lemon/bin_heap.h>
+#include <lemon/linear_heap.h>
+
+#include <stack>
+#include <functional>
+
+/// \ingroup topology
/// \file
/// \brief Topology related algorithms
///
/// Topology related algorithms
-///\todo Place the file contents is the module tree.
-namespace lemon {
+namespace lemon {
+
+ /// \ingroup topology
+ ///
+ /// \brief Check that the given undirected graph is connected.
+ ///
+ /// Check that the given undirected graph connected.
+ /// \param graph The undirected graph.
+ /// \return %True when there is path between any two nodes in the graph.
+ /// \warning The empty graph is not connected.
+ template <typename UndirGraph>
+ bool connected(const UndirGraph& graph) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::NodeIt NodeIt;
+ if (NodeIt(graph) == INVALID) return false;
+ Dfs<UndirGraph> dfs(graph);
+ dfs.run(NodeIt(graph));
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Count the number of connected components of an undirected graph
+ ///
+ /// Count the number of connected components of an undirected graph
+ ///
+ /// \param g The graph. In must be undirected.
+ /// \return The number of components
+ template <typename UndirGraph>
+ int countConnectedComponents(const UndirGraph &graph) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::Node Node;
+ typedef typename UndirGraph::Edge Edge;
+
+ typedef NullMap<Node, Edge> PredMap;
+ typedef NullMap<Node, int> DistMap;
+
+ int compNum = 0;
+ typename Bfs<UndirGraph>::
+ template DefPredMap<PredMap>::
+ template DefDistMap<DistMap>::
+ Create bfs(graph);
+
+ PredMap predMap;
+ bfs.predMap(predMap);
+
+ DistMap distMap;
+ bfs.distMap(distMap);
+
+ bfs.init();
+ for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (!bfs.reached(n)) {
+ bfs.addSource(n);
+ bfs.start();
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the connected components of an undirected graph
+ ///
+ /// Find the connected components of an undirected graph.
+ ///
+ /// \param g The graph. In must be undirected.
+ /// \retval comp A writable node map. The values will be set from 0 to
+ /// the number of the 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 <class UndirGraph, class NodeMap>
+ int connectedComponents(const UndirGraph &graph, NodeMap &compMap) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::Node Node;
+ typedef typename UndirGraph::Edge Edge;
+ checkConcept<concept::WriteMap<Node, int>, NodeMap>();
+
+ typedef NullMap<Node, Edge> PredMap;
+ typedef NullMap<Node, int> DistMap;
+
+ int compNum = 0;
+ typename Bfs<UndirGraph>::
+ template DefPredMap<PredMap>::
+ template DefDistMap<DistMap>::
+ Create bfs(graph);
+
+ PredMap predMap;
+ bfs.predMap(predMap);
+
+ DistMap distMap;
+ bfs.distMap(distMap);
+
+ bfs.init();
+ for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if(!bfs.reached(n)) {
+ bfs.addSource(n);
+ while (!bfs.emptyQueue()) {
+ compMap.set(bfs.nextNode(), compNum);
+ bfs.processNextNode();
+ }
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ namespace _topology_bits {
+
+ template <typename Graph, typename Iterator >
+ struct LeaveOrderVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ LeaveOrderVisitor(Iterator it) : _it(it) {}
+
+ void leave(const Node& node) {
+ *(_it++) = node;
+ }
+
+ private:
+ Iterator _it;
+ };
+
+ template <typename Graph, typename Map>
+ struct FillMapVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Map::Value Value;
+
+ FillMapVisitor(Map& map, Value& value)
+ : _map(map), _value(value) {}
+
+ void reach(const Node& node) {
+ _map.set(node, _value);
+ }
+ private:
+ Map& _map;
+ Value& _value;
+ };
+
+ template <typename Graph, typename EdgeMap>
+ struct StronglyConnectedCutEdgesVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+
+ StronglyConnectedCutEdgesVisitor(const Graph& graph, EdgeMap& cutMap,
+ int& cutNum)
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
+ _compMap(graph), _num(0) {
+ }
+
+ void stop(const Node&) {
+ ++_num;
+ }
+
+ void reach(const Node& node) {
+ _compMap.set(node, _num);
+ }
+
+ void examine(const Edge& edge) {
+ if (_compMap[_graph.source(edge)] != _compMap[_graph.target(edge)]) {
+ _cutMap.set(edge, true);
+ ++_cutNum;
+ }
+ }
+ private:
+ const Graph& _graph;
+ EdgeMap& _cutMap;
+ int& _cutNum;
+
+ typename Graph::template NodeMap<int> _compMap;
+ int _num;
+ };
+
+ }
+
+
+ /// \ingroup topology
+ ///
+ /// \brief Check that the given directed graph is strongly connected.
+ ///
+ /// Check that the given directed graph is strongly connected. The
+ /// graph is strongly connected when any two nodes of the graph are
+ /// connected with directed pathes in both direction.
+ /// \return %False when the graph is not strongly connected.
+ /// \see connected
+ ///
+ /// \waning Empty graph is not strongly connected.
+ template <typename Graph>
+ bool stronglyConnected(const Graph& graph) {
+ checkConcept<concept::StaticGraph, Graph>();
+ if (NodeIt(graph) == INVALID) return false;
+
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+
+ using namespace _topology_bits;
+
+ typedef DfsVisitor<Graph> Visitor;
+ Visitor visitor;
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+ dfs.addSource(NodeIt(graph));
+ dfs.start();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ return false;
+ }
+ }
+
+ typedef RevGraphAdaptor<const Graph> RGraph;
+ RGraph rgraph(graph);
+
+ typedef DfsVisitor<Graph> RVisitor;
+ RVisitor rvisitor;
+
+ DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
+ rdfs.init();
+ rdfs.addSource(NodeIt(graph));
+ rdfs.start();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!rdfs.reached(it)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Count the strongly connected components of a directed graph
+ ///
+ /// Count the strongly connected components of a directed graph.
+ /// The strongly connected components are the classes of an equivalence
+ /// relation on the nodes of the graph. Two nodes are connected with
+ /// directed paths in both direction.
+ ///
+ /// \param g The graph.
+ /// \return The number of components
+ template <typename Graph>
+ int countStronglyConnectedComponents(const Graph& graph) {
+ checkConcept<concept::StaticGraph, Graph>();
+
+ using namespace _topology_bits;
+
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::EdgeIt EdgeIt;
+
+ typedef std::vector<Node> Container;
+ typedef typename Container::iterator Iterator;
+
+ Container nodes(countNodes(graph));
+ typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
+ Visitor visitor(nodes.begin());
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+
+ typedef typename Container::reverse_iterator RIterator;
+ typedef RevGraphAdaptor<const Graph> RGraph;
+
+ RGraph rgraph(graph);
+
+ typedef DfsVisitor<Graph> RVisitor;
+ RVisitor rvisitor;
+
+ DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
+
+ int compNum = 0;
+
+ rdfs.init();
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
+ if (!rdfs.reached(*it)) {
+ rdfs.addSource(*it);
+ rdfs.start();
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the strongly connected components of a directed graph
+ ///
+ /// Find the strongly connected components of a directed graph.
+ /// The strongly connected components are the classes of an equivalence
+ /// relation on the nodes of the graph. Two nodes are in relationship
+ /// when there are directed paths between them in both direction.
+ ///
+ /// \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 <typename Graph, typename NodeMap>
+ int stronglyConnectedComponents(const Graph& graph, NodeMap& compMap) {
+ checkConcept<concept::StaticGraph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ checkConcept<concept::WriteMap<Node, int>, NodeMap>();
+
+ using namespace _topology_bits;
+
+ typedef std::vector<Node> Container;
+ typedef typename Container::iterator Iterator;
+
+ Container nodes(countNodes(graph));
+ typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
+ Visitor visitor(nodes.begin());
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+
+ typedef typename Container::reverse_iterator RIterator;
+ typedef RevGraphAdaptor<const Graph> RGraph;
+
+ RGraph rgraph(graph);
+
+ int compNum = 0;
+
+ typedef FillMapVisitor<RGraph, NodeMap> RVisitor;
+ RVisitor rvisitor(compMap, compNum);
+
+ DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
+
+ rdfs.init();
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
+ if (!rdfs.reached(*it)) {
+ rdfs.addSource(*it);
+ rdfs.start();
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the cut edges of the strongly connected components.
+ ///
+ /// Find the cut edges of the strongly connected components.
+ /// The strongly connected components are the classes of an equivalence
+ /// relation on the nodes of the graph. Two nodes are in relationship
+ /// when there are directed paths between them in both direction.
+ /// The strongly connected components are separated by the cut edges.
+ ///
+ /// \param g The graph.
+ /// \retval comp A writable edge map. The values will be set true when
+ /// the edge is cut edge otherwise false.
+ ///
+ /// \return The number of cut edges
+ template <typename Graph, typename EdgeMap>
+ int stronglyConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
+ checkConcept<concept::StaticGraph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::NodeIt NodeIt;
+ checkConcept<concept::WriteMap<Edge, bool>, EdgeMap>();
+
+ using namespace _topology_bits;
+
+ typedef std::vector<Node> Container;
+ typedef typename Container::iterator Iterator;
+
+ Container nodes(countNodes(graph));
+ typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
+ Visitor visitor(nodes.begin());
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+
+ typedef typename Container::reverse_iterator RIterator;
+ typedef RevGraphAdaptor<const Graph> RGraph;
+
+ RGraph rgraph(graph);
+
+ int cutNum = 0;
+
+ typedef StronglyConnectedCutEdgesVisitor<RGraph, EdgeMap> RVisitor;
+ RVisitor rvisitor(rgraph, cutMap, cutNum);
+
+ DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
+
+ rdfs.init();
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
+ if (!rdfs.reached(*it)) {
+ rdfs.addSource(*it);
+ rdfs.start();
+ }
+ }
+ return cutNum;
+ }
+
+ namespace _topology_bits {
+
+ template <typename Graph>
+ class CountNodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ CountNodeBiconnectedComponentsVisitor(const Graph& graph, int &compNum)
+ : _graph(graph), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void discover(const Edge& edge) {
+ _predMap.set(_graph.target(edge), _graph.source(edge));
+ }
+
+ void examine(const Edge& edge) {
+ if (_graph.source(edge) == _graph.target(edge) &&
+ _graph.direction(edge)) {
+ ++_compNum;
+ return;
+ }
+ if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Edge& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
+ ++_compNum;
+ }
+ }
+
+ private:
+ const Graph& _graph;
+ int& _compNum;
+
+ typename Graph::template NodeMap<int> _numMap;
+ typename Graph::template NodeMap<int> _retMap;
+ typename Graph::template NodeMap<Node> _predMap;
+ int _num;
+ };
+
+ template <typename Graph, typename EdgeMap>
+ class NodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ NodeBiconnectedComponentsVisitor(const Graph& graph,
+ EdgeMap& compMap, int &compNum)
+ : _graph(graph), _compMap(compMap), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void discover(const Edge& edge) {
+ Node target = _graph.target(edge);
+ _predMap.set(target, edge);
+ _edgeStack.push(edge);
+ }
+
+ void examine(const Edge& edge) {
+ Node source = _graph.source(edge);
+ Node target = _graph.target(edge);
+ if (source == target && _graph.direction(edge)) {
+ _compMap.set(edge, _compNum);
+ ++_compNum;
+ return;
+ }
+ if (_numMap[target] < _numMap[source]) {
+ if (_predMap[source] != _graph.oppositeEdge(edge)) {
+ _edgeStack.push(edge);
+ }
+ }
+ if (_predMap[source] != INVALID &&
+ target == _graph.source(_predMap[source])) {
+ return;
+ }
+ if (_retMap[source] > _numMap[target]) {
+ _retMap.set(source, _numMap[target]);
+ }
+ }
+
+ void backtrack(const Edge& edge) {
+ Node source = _graph.source(edge);
+ Node target = _graph.target(edge);
+ if (_retMap[source] > _retMap[target]) {
+ _retMap.set(source, _retMap[target]);
+ }
+ if (_numMap[source] <= _retMap[target]) {
+ while (_edgeStack.top() != edge) {
+ _compMap.set(_edgeStack.top(), _compNum);
+ _edgeStack.pop();
+ }
+ _compMap.set(edge, _compNum);
+ _edgeStack.pop();
+ ++_compNum;
+ }
+ }
+
+ private:
+ const Graph& _graph;
+ EdgeMap& _compMap;
+ int& _compNum;
+
+ typename Graph::template NodeMap<int> _numMap;
+ typename Graph::template NodeMap<int> _retMap;
+ typename Graph::template NodeMap<Edge> _predMap;
+ std::stack<UndirEdge> _edgeStack;
+ int _num;
+ };
+
+
+ template <typename Graph, typename NodeMap>
+ class NodeBiconnectedCutNodesVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ NodeBiconnectedCutNodesVisitor(const Graph& graph, NodeMap& cutMap,
+ int& cutNum)
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ rootCut = false;
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void discover(const Edge& edge) {
+ _predMap.set(_graph.target(edge), _graph.source(edge));
+ }
+
+ void examine(const Edge& edge) {
+ if (_graph.source(edge) == _graph.target(edge) &&
+ _graph.direction(edge)) {
+ if (!_cutMap[_graph.source(edge)]) {
+ _cutMap.set(_graph.source(edge), true);
+ ++_cutNum;
+ }
+ return;
+ }
+ if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
+ if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Edge& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
+ if (_predMap[_graph.source(edge)] != INVALID) {
+ if (!_cutMap[_graph.source(edge)]) {
+ _cutMap.set(_graph.source(edge), true);
+ ++_cutNum;
+ }
+ } else if (rootCut) {
+ if (!_cutMap[_graph.source(edge)]) {
+ _cutMap.set(_graph.source(edge), true);
+ ++_cutNum;
+ }
+ } else {
+ rootCut = true;
+ }
+ }
+ }
+
+ private:
+ const Graph& _graph;
+ NodeMap& _cutMap;
+ int& _cutNum;
+
+ typename Graph::template NodeMap<int> _numMap;
+ typename Graph::template NodeMap<int> _retMap;
+ typename Graph::template NodeMap<Node> _predMap;
+ std::stack<UndirEdge> _edgeStack;
+ int _num;
+ bool rootCut;
+ };
+
+ }
+
+ template <typename UndirGraph>
+ int countNodeBiconnectedComponents(const UndirGraph& graph);
+
+ /// \ingroup topology
+ ///
+ /// \brief Checks the graph is node biconnected.
+ ///
+ /// This function checks that the undirected graph is node biconnected
+ /// graph. The graph is node biconnected if any two undirected edge is
+ /// on same circle.
+ ///
+ /// \param graph The graph.
+ /// \return %True when the graph node biconnected.
+ /// \todo Make it faster.
+ template <typename UndirGraph>
+ bool nodeBiconnected(const UndirGraph& graph) {
+ return countNodeBiconnectedComponents(graph) == 1;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Count the biconnected components.
+ ///
+ /// This function finds the node biconnected components in an undirected
+ /// graph. The biconnected components are the classes of an equivalence
+ /// relation on the undirected edges. Two undirected edge is in relationship
+ /// when they are on same circle.
+ ///
+ /// \param graph The graph.
+ /// \return The number of components.
+ template <typename UndirGraph>
+ int countNodeBiconnectedComponents(const UndirGraph& graph) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::NodeIt NodeIt;
+
+ using namespace _topology_bits;
+
+ typedef CountNodeBiconnectedComponentsVisitor<UndirGraph> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compNum);
+
+ DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the node biconnected components.
+ ///
+ /// This function finds the node biconnected components in an undirected
+ /// graph. The node biconnected components are the classes of an equivalence
+ /// relation on the undirected edges. Two undirected edge are in relationship
+ /// when they are on same circle.
+ ///
+ /// \param graph The graph.
+ /// \retval comp A writable undir edge map. The values will be set from 0 to
+ /// the number of the biconnected 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 <typename UndirGraph, typename UndirEdgeMap>
+ int nodeBiconnectedComponents(const UndirGraph& graph,
+ UndirEdgeMap& compMap) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::NodeIt NodeIt;
+ typedef typename UndirGraph::UndirEdge UndirEdge;
+ checkConcept<concept::WriteMap<UndirEdge, int>, UndirEdgeMap>();
+
+ using namespace _topology_bits;
+
+ typedef NodeBiconnectedComponentsVisitor<UndirGraph, UndirEdgeMap> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compMap, compNum);
+
+ DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the node biconnected cut nodes.
+ ///
+ /// This function finds the node biconnected cut nodes in an undirected
+ /// graph. The node biconnected components are the classes of an equivalence
+ /// relation on the undirected edges. Two undirected edges are in
+ /// relationship when they are on same circle. The biconnected components
+ /// are separted by nodes which are the cut nodes of the components.
+ ///
+ /// \param graph The graph.
+ /// \retval comp A writable edge map. The values will be set true when
+ /// the node separate two or more components.
+ /// \return The number of the cut nodes.
+ template <typename UndirGraph, typename NodeMap>
+ int nodeBiconnectedCutNodes(const UndirGraph& graph, NodeMap& cutMap) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::Node Node;
+ typedef typename UndirGraph::NodeIt NodeIt;
+ checkConcept<concept::WriteMap<Node, bool>, NodeMap>();
+
+ using namespace _topology_bits;
+
+ typedef NodeBiconnectedCutNodesVisitor<UndirGraph, NodeMap> Visitor;
+
+ int cutNum = 0;
+ Visitor visitor(graph, cutMap, cutNum);
+
+ DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return cutNum;
+ }
+
+ namespace _topology_bits {
+
+ template <typename Graph>
+ class CountEdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ CountEdgeBiconnectedComponentsVisitor(const Graph& graph, int &compNum)
+ : _graph(graph), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void leave(const Node& node) {
+ if (_numMap[node] <= _retMap[node]) {
+ ++_compNum;
+ }
+ }
+
+ void discover(const Edge& edge) {
+ _predMap.set(_graph.target(edge), edge);
+ }
+
+ void examine(const Edge& edge) {
+ if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Edge& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ private:
+ const Graph& _graph;
+ int& _compNum;
+
+ typename Graph::template NodeMap<int> _numMap;
+ typename Graph::template NodeMap<int> _retMap;
+ typename Graph::template NodeMap<Edge> _predMap;
+ int _num;
+ };
+
+ template <typename Graph, typename NodeMap>
+ class EdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ EdgeBiconnectedComponentsVisitor(const Graph& graph,
+ NodeMap& compMap, int &compNum)
+ : _graph(graph), _compMap(compMap), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ _nodeStack.push(node);
+ ++_num;
+ }
+
+ void leave(const Node& node) {
+ if (_numMap[node] <= _retMap[node]) {
+ while (_nodeStack.top() != node) {
+ _compMap.set(_nodeStack.top(), _compNum);
+ _nodeStack.pop();
+ }
+ _compMap.set(node, _compNum);
+ _nodeStack.pop();
+ ++_compNum;
+ }
+ }
+
+ void discover(const Edge& edge) {
+ _predMap.set(_graph.target(edge), edge);
+ }
+
+ void examine(const Edge& edge) {
+ if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Edge& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ private:
+ const Graph& _graph;
+ NodeMap& _compMap;
+ int& _compNum;
+
+ typename Graph::template NodeMap<int> _numMap;
+ typename Graph::template NodeMap<int> _retMap;
+ typename Graph::template NodeMap<Edge> _predMap;
+ std::stack<Node> _nodeStack;
+ int _num;
+ };
+
+
+ template <typename Graph, typename EdgeMap>
+ class EdgeBiconnectedCutEdgesVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UndirEdge UndirEdge;
+
+ EdgeBiconnectedCutEdgesVisitor(const Graph& graph,
+ EdgeMap& cutMap, int &cutNum)
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap[node] = INVALID;
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void leave(const Node& node) {
+ if (_numMap[node] <= _retMap[node]) {
+ if (_predMap[node] != INVALID) {
+ _cutMap.set(_predMap[node], true);
+ ++_cutNum;
+ }
+ }
+ }
+
+ void discover(const Edge& edge) {
+ _predMap.set(_graph.target(edge), edge);
+ }
+
+ void examine(const Edge& edge) {
+ if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Edge& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ private:
+ const Graph& _graph;
+ EdgeMap& _cutMap;
+ int& _cutNum;
+
+ typename Graph::template NodeMap<int> _numMap;
+ typename Graph::template NodeMap<int> _retMap;
+ typename Graph::template NodeMap<Edge> _predMap;
+ int _num;
+ };
+ }
+
+ template <typename UndirGraph>
+ int countEdgeBiconnectedComponents(const UndirGraph& graph);
+
+ /// \ingroup topology
+ ///
+ /// \brief Checks that the graph is edge biconnected.
+ ///
+ /// This function checks that the graph is edge biconnected. The undirected
+ /// graph is edge biconnected when any two nodes are connected with two
+ /// edge-disjoint paths.
+ ///
+ /// \param graph The undirected graph.
+ /// \return The number of components.
+ /// \todo Make it faster.
+ template <typename UndirGraph>
+ bool edgeBiconnected(const UndirGraph& graph) {
+ return countEdgeBiconnectedComponents(graph) == 1;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Count the edge biconnected components.
+ ///
+ /// This function count the edge biconnected components in an undirected
+ /// graph. The edge biconnected components are the classes of an equivalence
+ /// relation on the nodes. Two nodes are in relationship when they are
+ /// connected with at least two edge-disjoint paths.
+ ///
+ /// \param graph The undirected graph.
+ /// \return The number of components.
+ template <typename UndirGraph>
+ int countEdgeBiconnectedComponents(const UndirGraph& graph) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::NodeIt NodeIt;
+
+ using namespace _topology_bits;
- namespace _topology_bits {
+ typedef CountEdgeBiconnectedComponentsVisitor<UndirGraph> Visitor;
- template <typename NodeMap>
- class BackCounterMap {
- public:
- BackCounterMap(NodeMap& _nodeMap, int _counter)
- : nodeMap(_nodeMap), counter(_counter) {}
+ int compNum = 0;
+ Visitor visitor(graph, compNum);
- void set(typename NodeMap::Key key, bool val) {
- if (val) {
- nodeMap.set(key, --counter);
- } else {
- nodeMap.set(key, -1);
- }
+ DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the edge biconnected components.
+ ///
+ /// This function finds the edge biconnected components in an undirected
+ /// graph. The edge biconnected components are the classes of an equivalence
+ /// relation on the nodes. Two nodes are in relationship when they are
+ /// connected at least two edge-disjoint paths.
+ ///
+ /// \param graph The graph.
+ /// \retval comp A writable node map. The values will be set from 0 to
+ /// the number of the biconnected 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 <typename UndirGraph, typename NodeMap>
+ int edgeBiconnectedComponents(const UndirGraph& graph, NodeMap& compMap) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::NodeIt NodeIt;
+ typedef typename UndirGraph::Node Node;
+ checkConcept<concept::WriteMap<Node, int>, NodeMap>();
+
+ using namespace _topology_bits;
+
+ typedef EdgeBiconnectedComponentsVisitor<UndirGraph, NodeMap> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compMap, compNum);
+
+ DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Find the edge biconnected cut edges.
+ ///
+ /// This function finds the edge biconnected components in an undirected
+ /// graph. The edge biconnected components are the classes of an equivalence
+ /// relation on the nodes. Two nodes are in relationship when they are
+ /// connected with at least two edge-disjoint paths. The edge biconnected
+ /// components are separted by edges which are the cut edges of the
+ /// components.
+ ///
+ /// \param graph The graph.
+ /// \retval comp A writable node map. The values will be set true when the
+ /// edge is a cut edge.
+ /// \return The number of cut edges.
+ template <typename UndirGraph, typename UndirEdgeMap>
+ int edgeBiconnectedCutEdges(const UndirGraph& graph, UndirEdgeMap& cutMap) {
+ checkConcept<concept::UndirGraph, UndirGraph>();
+ typedef typename UndirGraph::NodeIt NodeIt;
+ typedef typename UndirGraph::UndirEdge UndirEdge;
+ checkConcept<concept::WriteMap<UndirEdge, bool>, UndirEdgeMap>();
+
+ using namespace _topology_bits;
+
+ typedef EdgeBiconnectedCutEdgesVisitor<UndirGraph, UndirEdgeMap> Visitor;
+
+ int cutNum = 0;
+ Visitor visitor(graph, cutMap, cutNum);
+
+ DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
}
+ }
+ return cutNum;
+ }
+
+
+ namespace _topology_bits {
+
+ template <typename Graph, typename IntNodeMap>
+ class TopologicalSortVisitor : public DfsVisitor<Graph> {
+ public:
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge edge;
- bool operator[](typename NodeMap::Key key) const {
- return nodeMap[key] != -1;
+ TopologicalSortVisitor(IntNodeMap& order, int num)
+ : _order(order), _num(num) {}
+
+ void leave(const Node& node) {
+ _order.set(node, --_num);
}
private:
- NodeMap& nodeMap;
- int counter;
+ IntNodeMap& _order;
+ int _num;
};
+
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Sort the nodes of a DAG into topolgical order.
+ ///
+ /// Sort the nodes of a DAG into topolgical order.
+ ///
+ /// \param g The graph. In must be directed and acyclic.
+ /// \retval comp A writable node map. The values will be set from 0 to
+ /// the number of the nodes in the graph minus one. Each values of the map
+ /// will be set exactly once, the values will be set descending order.
+ ///
+ /// \see checkedTopologicalSort
+ /// \see dag
+ template <typename Graph, typename NodeMap>
+ void topologicalSort(const Graph& graph, NodeMap& order) {
+ using namespace _topology_bits;
+
+ checkConcept<concept::StaticGraph, Graph>();
+ checkConcept<concept::WriteMap<typename Graph::Node, int>, NodeMap>();
+
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Edge Edge;
+
+ TopologicalSortVisitor<Graph, NodeMap>
+ visitor(order, countNodes(graph));
+
+ DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
+ dfs(graph, visitor);
+
+ dfs.init();
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
}
- // \todo Its to special output // ReadWriteMap
+ /// \ingroup topology
+ ///
+ /// \brief Sort the nodes of a DAG into topolgical order.
+ ///
+ /// Sort the nodes of a DAG into topolgical order. It also checks
+ /// that the given graph is DAG.
+ ///
+ /// \param g The graph. In must be directed and acyclic.
+ /// \retval order A readable - writable node map. The values will be set
+ /// from 0 to the number of the nodes in the graph minus one. Each values
+ /// of the map will be set exactly once, the values will be set descending
+ /// order.
+ /// \return %False when the graph is not DAG.
+ ///
+ /// \see topologicalSort
+ /// \see dag
template <typename Graph, typename NodeMap>
- bool topological_sort(const Graph& graph, NodeMap& nodeMap) {
+ bool checkedTopologicalSort(const Graph& graph, NodeMap& order) {
using namespace _topology_bits;
checkConcept<concept::StaticGraph, Graph>();
@@ -72,35 +1231,39 @@
typedef typename Graph::NodeIt NodeIt;
typedef typename Graph::Edge Edge;
- typedef BackCounterMap<NodeMap> ProcessedMap;
+ order = constMap<Node, int, -1>();
- typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
- Create dfs(graph);
+ TopologicalSortVisitor<Graph, NodeMap>
+ visitor(order, countNodes(graph));
- ProcessedMap processed(nodeMap, countNodes(graph));
+ DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
+ dfs(graph, visitor);
- dfs.processedMap(processed);
dfs.init();
for (NodeIt it(graph); it != INVALID; ++it) {
if (!dfs.reached(it)) {
dfs.addSource(it);
while (!dfs.emptyQueue()) {
- Edge edge = dfs.nextEdge();
- Node target = graph.target(edge);
- if (dfs.reached(target) && !processed[target]) {
- return false;
- }
- dfs.processNextEdge();
- }
+ Edge edge = dfs.nextEdge();
+ Node target = graph.target(edge);
+ if (dfs.reached(target) && order[target] == -1) {
+ return false;
+ }
+ dfs.processNextEdge();
+ }
}
- }
+ }
return true;
}
- /// \brief Check that the given graph is a DAG.
+ /// \ingroup topology
///
- /// Check that the given graph is a DAG. The DAG is
+ /// \brief Check that the given directed graph is a DAG.
+ ///
+ /// Check that the given directed graph is a DAG. The DAG is
/// an Directed Acyclic Graph.
+ /// \return %False when the graph is not DAG.
+ /// \see acyclic
template <typename Graph>
bool dag(const Graph& graph) {
@@ -135,29 +1298,14 @@
return true;
}
- // UndirGraph algorithms
-
- /// \brief Check that the given undirected graph is connected.
+ /// \ingroup topology
///
- /// Check that the given undirected graph connected.
- template <typename UndirGraph>
- bool connected(const UndirGraph& graph) {
- checkConcept<concept::UndirGraph, UndirGraph>();
- typedef typename UndirGraph::NodeIt NodeIt;
- if (NodeIt(graph) == INVALID) return false;
- Dfs<UndirGraph> dfs(graph);
- dfs.run(NodeIt(graph));
- for (NodeIt it(graph); it != INVALID; ++it) {
- if (!dfs.reached(it)) {
- return false;
- }
- }
- return true;
- }
-
/// \brief Check that the given undirected graph is acyclic.
///
/// Check that the given undirected graph acyclic.
+ /// \param graph The undirected graph.
+ /// \return %True when there is no circle in the graph.
+ /// \see dag
template <typename UndirGraph>
bool acyclic(const UndirGraph& graph) {
checkConcept<concept::UndirGraph, UndirGraph>();
@@ -184,16 +1332,19 @@
return true;
}
+ /// \ingroup topology
+ ///
/// \brief Check that the given undirected graph is tree.
///
/// Check that the given undirected graph is tree.
+ /// \param graph The undirected graph.
+ /// \return %True when the graph is acyclic and connected.
template <typename UndirGraph>
bool tree(const UndirGraph& graph) {
checkConcept<concept::UndirGraph, UndirGraph>();
typedef typename UndirGraph::Node Node;
typedef typename UndirGraph::NodeIt NodeIt;
typedef typename UndirGraph::Edge Edge;
- if (NodeIt(graph) == INVALID) return false;
Dfs<UndirGraph> dfs(graph);
dfs.init();
dfs.addSource(NodeIt(graph));
@@ -214,208 +1365,45 @@
}
return true;
}
-
- ///Count the number of connected components of an undirected graph
- ///Count the number of connected components of an undirected graph
+ /// \ingroup topology
///
- ///\param g The graph. In must be undirected.
- ///\return The number of components
- template <class UndirGraph>
- int countConnectedComponents(const UndirGraph &g) {
- checkConcept<concept::UndirGraph, UndirGraph>();
- int c = 0;
- Bfs<UndirGraph> bfs(g);
- bfs.init();
- for(typename UndirGraph::NodeIt n(g); n != INVALID; ++n) {
- if(!bfs.reached(n)) {
- bfs.addSource(n);
- bfs.start();
- ++c;
- }
- }
- return c;
- }
-
-
- ///Find the connected components of an undirected graph
-
- ///Find the connected components of an undirected graph
+ /// \brief Check that the given undirected graph is bipartite.
///
- ///\param g The graph. In must be undirected.
- ///\retval comp A writable node map. The values will be set from 0 to
- ///the number of the 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
- ///\todo Test required
- template <class UndirGraph, class IntNodeMap>
- int connectedComponents(const UndirGraph &g, IntNodeMap &comp) {
+ /// Check that the given undirected graph is bipartite.
+ /// \param graph The undirected graph.
+ /// \return %True when the nodes can be separated into two sets that
+ /// there are not connected nodes in neither sets.
+ template <typename UndirGraph>
+ bool bipartite(const UndirGraph& graph) {
checkConcept<concept::UndirGraph, UndirGraph>();
- checkConcept<concept::WriteMap<typename UndirGraph::Node, int>,
- IntNodeMap>();
- int c = 0;
- Bfs<UndirGraph> bfs(g);
- bfs.init();
- for(typename UndirGraph::NodeIt n(g); n != INVALID; ++n) {
- if(!bfs.reached(n)) {
- bfs.addSource(n);
- while (!bfs.emptyQueue()) {
- comp[bfs.nextNode()] = c;
- bfs.processNextNode();
- }
- ++c;
- }
- }
- return c;
- }
-
- namespace _components_bits {
-
- template <typename Key, typename IntMap>
- struct FillWriteMap : public MapBase<Key, bool> {
- 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 <typename Key, typename Container = std::vector<Key> >
- struct BackInserterWriteMap : public MapBase<Key, bool> {
- 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 <typename Graph>
- int countStronglyConnectedComponents(const Graph& graph) {
- checkConcept<concept::StaticGraph, Graph>();
-
- 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<Graph>::
- template DefProcessedMap<BackInserterWriteMap<Node> >::
- Create dfs(graph);
-
- std::vector<Node> nodes;
- BackInserterWriteMap<Node> 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<const Graph> RGraph;
-
- RGraph rgraph(graph);
-
- Dfs<RGraph> rdfs(rgraph);
-
- int num = 0;
-
- rdfs.init();
- for (typename std::vector<Node>::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 <typename Graph, typename IntNodeMap>
- int stronglyConnectedComponents(const Graph& graph, IntNodeMap& comp) {
- checkConcept<concept::StaticGraph, Graph>();
- checkConcept<concept::WriteMap<typename Graph::Node, int>, 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<Graph>::
- template DefProcessedMap<BackInserterWriteMap<Node> >::
- Create dfs(graph);
-
- std::vector<Node> nodes;
- BackInserterWriteMap<Node> processed(nodes);
- dfs.processedMap(processed);
-
+ typedef typename UndirGraph::Node Node;
+ typedef typename UndirGraph::NodeIt NodeIt;
+ typedef typename UndirGraph::Edge Edge;
+ if (NodeIt(graph) == INVALID) return false;
+ Dfs<UndirGraph> dfs(graph);
dfs.init();
+ typename UndirGraph::template NodeMap<bool> red(graph);
for (NodeIt it(graph); it != INVALID; ++it) {
if (!dfs.reached(it)) {
dfs.addSource(it);
- dfs.start();
- }
- }
-
- typedef RevGraphAdaptor<const Graph> RGraph;
-
- RGraph rgraph(graph);
-
- typename Dfs<RGraph>::
- template DefProcessedMap<FillWriteMap<Node, IntNodeMap> >::
- Create rdfs(rgraph);
-
- int num = 0;
- FillWriteMap<Node, IntNodeMap> rprocessed(comp, num);
- rdfs.processedMap(rprocessed);
-
- rdfs.init();
- for (typename std::vector<Node>::reverse_iterator
- it = nodes.rbegin(); it != nodes.rend(); ++it) {
- if (!rdfs.reached(*it)) {
- rdfs.addSource(*it);
- rdfs.start();
- ++num;
+ red[it] = true;
+ while (!dfs.emptyQueue()) {
+ Edge edge = dfs.nextEdge();
+ Node source = graph.source(edge);
+ Node target = graph.target(edge);
+ if (dfs.reached(target) && red[source] == red[target]) {
+ return false;
+ } else {
+ red[target] = !red[source];
+ }
+ dfs.processNextEdge();
+ }
}
}
- return num;
+ return true;
}
-
+
} //namespace lemon
#endif //LEMON_TOPOLOGY_H
More information about the Lemon-commits
mailing list