deba@433: /* -*- mode: C++; indent-tabs-mode: nil; -*- deba@433: * deba@433: * This file is a part of LEMON, a generic C++ optimization library. deba@433: * alpar@463: * Copyright (C) 2003-2009 deba@433: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@433: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@433: * deba@433: * Permission to use, modify and distribute this software is granted deba@433: * provided that this copyright notice appears in all copies. For deba@433: * precise terms see the accompanying LICENSE file. deba@433: * deba@433: * This software is provided "AS IS" with no warranty of any kind, deba@433: * express or implied, and with no claim as to its suitability for any deba@433: * purpose. deba@433: * deba@433: */ deba@433: deba@435: #ifndef LEMON_CONNECTIVITY_H deba@435: #define LEMON_CONNECTIVITY_H deba@433: deba@433: #include deba@433: #include deba@433: #include deba@433: #include deba@433: #include deba@433: deba@433: #include deba@433: #include deba@433: #include deba@433: deba@433: #include deba@433: #include deba@433: deba@433: /// \ingroup connectivity deba@433: /// \file deba@433: /// \brief Connectivity algorithms deba@433: /// deba@433: /// Connectivity algorithms deba@433: deba@433: namespace lemon { deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check whether the given undirected graph is connected. deba@433: /// deba@433: /// Check whether the given undirected graph is connected. deba@433: /// \param graph The undirected graph. kpeter@606: /// \return \c true when there is path between any two nodes in the graph. deba@433: /// \note By definition, the empty graph is connected. deba@433: template deba@433: bool connected(const Graph& graph) { deba@433: checkConcept(); deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: if (NodeIt(graph) == INVALID) return true; deba@433: Dfs dfs(graph); deba@433: dfs.run(NodeIt(graph)); deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: return false; deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Count the number of connected components of an undirected graph deba@433: /// deba@433: /// Count the number of connected components of an undirected graph deba@433: /// deba@433: /// \param graph The graph. It must be undirected. deba@433: /// \return The number of components deba@433: /// \note By definition, the empty graph consists deba@433: /// of zero connected components. deba@433: template deba@433: int countConnectedComponents(const Graph &graph) { deba@433: checkConcept(); deba@433: typedef typename Graph::Node Node; deba@433: typedef typename Graph::Arc Arc; deba@433: deba@433: typedef NullMap PredMap; deba@433: typedef NullMap DistMap; deba@433: deba@433: int compNum = 0; deba@433: typename Bfs:: deba@433: template SetPredMap:: deba@433: template SetDistMap:: deba@433: Create bfs(graph); deba@433: deba@433: PredMap predMap; deba@433: bfs.predMap(predMap); deba@433: deba@433: DistMap distMap; deba@433: bfs.distMap(distMap); deba@433: deba@433: bfs.init(); deba@433: for(typename Graph::NodeIt n(graph); n != INVALID; ++n) { deba@433: if (!bfs.reached(n)) { deba@433: bfs.addSource(n); deba@433: bfs.start(); deba@433: ++compNum; deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the connected components of an undirected graph deba@433: /// deba@433: /// Find the connected components of an undirected graph. deba@433: /// deba@433: /// \param graph The graph. It must be undirected. deba@433: /// \retval compMap A writable node map. The values will be set from 0 to deba@433: /// the number of the connected components minus one. Each values of the map deba@433: /// will be set exactly once, the values of a certain component will be deba@433: /// set continuously. deba@433: /// \return The number of components deba@433: /// deba@433: template deba@433: int connectedComponents(const Graph &graph, NodeMap &compMap) { deba@433: checkConcept(); deba@433: typedef typename Graph::Node Node; deba@433: typedef typename Graph::Arc Arc; deba@433: checkConcept, NodeMap>(); deba@433: deba@433: typedef NullMap PredMap; deba@433: typedef NullMap DistMap; deba@433: deba@433: int compNum = 0; deba@433: typename Bfs:: deba@433: template SetPredMap:: deba@433: template SetDistMap:: deba@433: Create bfs(graph); deba@433: deba@433: PredMap predMap; deba@433: bfs.predMap(predMap); deba@433: deba@433: DistMap distMap; deba@433: bfs.distMap(distMap); deba@433: deba@433: bfs.init(); deba@433: for(typename Graph::NodeIt n(graph); n != INVALID; ++n) { deba@433: if(!bfs.reached(n)) { deba@433: bfs.addSource(n); deba@433: while (!bfs.emptyQueue()) { deba@433: compMap.set(bfs.nextNode(), compNum); deba@433: bfs.processNextNode(); deba@433: } deba@433: ++compNum; deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@435: namespace _connectivity_bits { deba@433: deba@433: template deba@433: struct LeaveOrderVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: LeaveOrderVisitor(Iterator it) : _it(it) {} deba@433: deba@433: void leave(const Node& node) { deba@433: *(_it++) = node; deba@433: } deba@433: deba@433: private: deba@433: Iterator _it; deba@433: }; deba@433: deba@433: template deba@433: struct FillMapVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Map::Value Value; deba@433: deba@433: FillMapVisitor(Map& map, Value& value) deba@433: : _map(map), _value(value) {} deba@433: deba@433: void reach(const Node& node) { deba@433: _map.set(node, _value); deba@433: } deba@433: private: deba@433: Map& _map; deba@433: Value& _value; deba@433: }; deba@433: deba@433: template deba@435: struct StronglyConnectedCutArcsVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: deba@435: StronglyConnectedCutArcsVisitor(const Digraph& digraph, deba@435: ArcMap& cutMap, deba@435: int& cutNum) deba@433: : _digraph(digraph), _cutMap(cutMap), _cutNum(cutNum), deba@435: _compMap(digraph, -1), _num(-1) { deba@433: } deba@433: deba@435: void start(const Node&) { deba@433: ++_num; deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _compMap.set(node, _num); deba@433: } deba@433: deba@433: void examine(const Arc& arc) { deba@433: if (_compMap[_digraph.source(arc)] != deba@433: _compMap[_digraph.target(arc)]) { deba@433: _cutMap.set(arc, true); deba@433: ++_cutNum; deba@433: } deba@433: } deba@433: private: deba@433: const Digraph& _digraph; deba@433: ArcMap& _cutMap; deba@433: int& _cutNum; deba@433: deba@433: typename Digraph::template NodeMap _compMap; deba@433: int _num; deba@433: }; deba@433: deba@433: } deba@433: deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check whether the given directed graph is strongly connected. deba@433: /// deba@433: /// Check whether the given directed graph is strongly connected. The deba@433: /// graph is strongly connected when any two nodes of the graph are deba@433: /// connected with directed paths in both direction. kpeter@606: /// \return \c false when the graph is not strongly connected. deba@433: /// \see connected deba@433: /// deba@433: /// \note By definition, the empty graph is strongly connected. deba@433: template deba@433: bool stronglyConnected(const Digraph& digraph) { deba@433: checkConcept(); deba@433: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: deba@433: typename Digraph::Node source = NodeIt(digraph); deba@433: if (source == INVALID) return true; deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef DfsVisitor Visitor; deba@433: Visitor visitor; deba@433: deba@433: DfsVisit dfs(digraph, visitor); deba@433: dfs.init(); deba@433: dfs.addSource(source); deba@433: dfs.start(); deba@433: deba@433: for (NodeIt it(digraph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: return false; deba@433: } deba@433: } deba@433: deba@433: typedef ReverseDigraph RDigraph; deba@435: typedef typename RDigraph::NodeIt RNodeIt; deba@433: RDigraph rdigraph(digraph); deba@433: deba@433: typedef DfsVisitor RVisitor; deba@433: RVisitor rvisitor; deba@433: deba@433: DfsVisit rdfs(rdigraph, rvisitor); deba@433: rdfs.init(); deba@433: rdfs.addSource(source); deba@433: rdfs.start(); deba@433: deba@435: for (RNodeIt it(rdigraph); it != INVALID; ++it) { deba@433: if (!rdfs.reached(it)) { deba@433: return false; deba@433: } deba@433: } deba@433: deba@433: return true; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Count the strongly connected components of a directed graph deba@433: /// deba@433: /// Count the strongly connected components of a directed graph. deba@433: /// The strongly connected components are the classes of an deba@433: /// equivalence relation on the nodes of the graph. Two nodes are in deba@433: /// the same class if they are connected with directed paths in both deba@433: /// direction. deba@433: /// deba@444: /// \param digraph The graph. deba@433: /// \return The number of components deba@433: /// \note By definition, the empty graph has zero deba@433: /// strongly connected components. deba@433: template deba@433: int countStronglyConnectedComponents(const Digraph& digraph) { deba@433: checkConcept(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: typedef typename Digraph::ArcIt ArcIt; deba@433: deba@433: typedef std::vector Container; deba@433: typedef typename Container::iterator Iterator; deba@433: deba@433: Container nodes(countNodes(digraph)); deba@433: typedef LeaveOrderVisitor Visitor; deba@433: Visitor visitor(nodes.begin()); deba@433: deba@433: DfsVisit dfs(digraph, visitor); deba@433: dfs.init(); deba@433: for (NodeIt it(digraph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: deba@433: typedef typename Container::reverse_iterator RIterator; deba@433: typedef ReverseDigraph RDigraph; deba@433: deba@433: RDigraph rdigraph(digraph); deba@433: deba@433: typedef DfsVisitor RVisitor; deba@433: RVisitor rvisitor; deba@433: deba@433: DfsVisit rdfs(rdigraph, rvisitor); deba@433: deba@433: int compNum = 0; deba@433: deba@433: rdfs.init(); deba@433: for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) { deba@433: if (!rdfs.reached(*it)) { deba@433: rdfs.addSource(*it); deba@433: rdfs.start(); deba@433: ++compNum; deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the strongly connected components of a directed graph deba@433: /// deba@433: /// Find the strongly connected components of a directed graph. The deba@433: /// strongly connected components are the classes of an equivalence deba@433: /// relation on the nodes of the graph. Two nodes are in deba@433: /// relationship when there are directed paths between them in both deba@433: /// direction. In addition, the numbering of components will satisfy deba@433: /// that there is no arc going from a higher numbered component to deba@433: /// a lower. deba@433: /// deba@433: /// \param digraph The digraph. deba@433: /// \retval compMap A writable node map. The values will be set from 0 to deba@433: /// the number of the strongly connected components minus one. Each value deba@433: /// of the map will be set exactly once, the values of a certain component deba@433: /// will be set continuously. deba@433: /// \return The number of components deba@433: /// deba@433: template deba@433: int stronglyConnectedComponents(const Digraph& digraph, NodeMap& compMap) { deba@433: checkConcept(); deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: checkConcept, NodeMap>(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef std::vector Container; deba@433: typedef typename Container::iterator Iterator; deba@433: deba@433: Container nodes(countNodes(digraph)); deba@433: typedef LeaveOrderVisitor Visitor; deba@433: Visitor visitor(nodes.begin()); deba@433: deba@433: DfsVisit dfs(digraph, visitor); deba@433: dfs.init(); deba@433: for (NodeIt it(digraph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: deba@433: typedef typename Container::reverse_iterator RIterator; deba@433: typedef ReverseDigraph RDigraph; deba@433: deba@433: RDigraph rdigraph(digraph); deba@433: deba@433: int compNum = 0; deba@433: deba@433: typedef FillMapVisitor RVisitor; deba@433: RVisitor rvisitor(compMap, compNum); deba@433: deba@433: DfsVisit rdfs(rdigraph, rvisitor); deba@433: deba@433: rdfs.init(); deba@433: for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) { deba@433: if (!rdfs.reached(*it)) { deba@433: rdfs.addSource(*it); deba@433: rdfs.start(); deba@433: ++compNum; deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the cut arcs of the strongly connected components. deba@433: /// deba@433: /// Find the cut arcs of the strongly connected components. deba@433: /// The strongly connected components are the classes of an equivalence deba@433: /// relation on the nodes of the graph. Two nodes are in relationship deba@433: /// when there are directed paths between them in both direction. deba@433: /// The strongly connected components are separated by the cut arcs. deba@433: /// deba@433: /// \param graph The graph. deba@433: /// \retval cutMap A writable node map. The values will be set true when the deba@433: /// arc is a cut arc. deba@433: /// deba@433: /// \return The number of cut arcs deba@433: template deba@433: int stronglyConnectedCutArcs(const Digraph& graph, ArcMap& cutMap) { deba@433: checkConcept(); deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: checkConcept, ArcMap>(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef std::vector Container; deba@433: typedef typename Container::iterator Iterator; deba@433: deba@433: Container nodes(countNodes(graph)); deba@433: typedef LeaveOrderVisitor Visitor; deba@433: Visitor visitor(nodes.begin()); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: deba@433: typedef typename Container::reverse_iterator RIterator; deba@433: typedef ReverseDigraph RDigraph; deba@433: deba@433: RDigraph rgraph(graph); deba@433: deba@433: int cutNum = 0; deba@433: deba@435: typedef StronglyConnectedCutArcsVisitor RVisitor; deba@433: RVisitor rvisitor(rgraph, cutMap, cutNum); deba@433: deba@433: DfsVisit rdfs(rgraph, rvisitor); deba@433: deba@433: rdfs.init(); deba@433: for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) { deba@433: if (!rdfs.reached(*it)) { deba@433: rdfs.addSource(*it); deba@433: rdfs.start(); deba@433: } deba@433: } deba@433: return cutNum; deba@433: } deba@433: deba@435: namespace _connectivity_bits { deba@433: deba@433: template deba@433: class CountBiNodeConnectedComponentsVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Edge Edge; deba@433: deba@433: CountBiNodeConnectedComponentsVisitor(const Digraph& graph, int &compNum) deba@433: : _graph(graph), _compNum(compNum), deba@433: _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {} deba@433: deba@433: void start(const Node& node) { deba@433: _predMap.set(node, INVALID); deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _numMap.set(node, _num); deba@433: _retMap.set(node, _num); deba@433: ++_num; deba@433: } deba@433: deba@433: void discover(const Arc& edge) { deba@433: _predMap.set(_graph.target(edge), _graph.source(edge)); deba@433: } deba@433: deba@433: void examine(const Arc& edge) { deba@433: if (_graph.source(edge) == _graph.target(edge) && deba@433: _graph.direction(edge)) { deba@433: ++_compNum; deba@433: return; deba@433: } deba@433: if (_predMap[_graph.source(edge)] == _graph.target(edge)) { deba@433: return; deba@433: } deba@433: if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: void backtrack(const Arc& edge) { deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) { deba@433: ++_compNum; deba@433: } deba@433: } deba@433: deba@433: private: deba@433: const Digraph& _graph; deba@433: int& _compNum; deba@433: deba@433: typename Digraph::template NodeMap _numMap; deba@433: typename Digraph::template NodeMap _retMap; deba@433: typename Digraph::template NodeMap _predMap; deba@433: int _num; deba@433: }; deba@433: deba@433: template deba@433: class BiNodeConnectedComponentsVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Edge Edge; deba@433: deba@433: BiNodeConnectedComponentsVisitor(const Digraph& graph, deba@433: ArcMap& compMap, int &compNum) deba@433: : _graph(graph), _compMap(compMap), _compNum(compNum), deba@433: _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {} deba@433: deba@433: void start(const Node& node) { deba@433: _predMap.set(node, INVALID); deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _numMap.set(node, _num); deba@433: _retMap.set(node, _num); deba@433: ++_num; deba@433: } deba@433: deba@433: void discover(const Arc& edge) { deba@433: Node target = _graph.target(edge); deba@433: _predMap.set(target, edge); deba@433: _edgeStack.push(edge); deba@433: } deba@433: deba@433: void examine(const Arc& edge) { deba@433: Node source = _graph.source(edge); deba@433: Node target = _graph.target(edge); deba@433: if (source == target && _graph.direction(edge)) { deba@433: _compMap.set(edge, _compNum); deba@433: ++_compNum; deba@433: return; deba@433: } deba@433: if (_numMap[target] < _numMap[source]) { deba@433: if (_predMap[source] != _graph.oppositeArc(edge)) { deba@433: _edgeStack.push(edge); deba@433: } deba@433: } deba@433: if (_predMap[source] != INVALID && deba@433: target == _graph.source(_predMap[source])) { deba@433: return; deba@433: } deba@433: if (_retMap[source] > _numMap[target]) { deba@433: _retMap.set(source, _numMap[target]); deba@433: } deba@433: } deba@433: deba@433: void backtrack(const Arc& edge) { deba@433: Node source = _graph.source(edge); deba@433: Node target = _graph.target(edge); deba@433: if (_retMap[source] > _retMap[target]) { deba@433: _retMap.set(source, _retMap[target]); deba@433: } deba@433: if (_numMap[source] <= _retMap[target]) { deba@433: while (_edgeStack.top() != edge) { deba@433: _compMap.set(_edgeStack.top(), _compNum); deba@433: _edgeStack.pop(); deba@433: } deba@433: _compMap.set(edge, _compNum); deba@433: _edgeStack.pop(); deba@433: ++_compNum; deba@433: } deba@433: } deba@433: deba@433: private: deba@433: const Digraph& _graph; deba@433: ArcMap& _compMap; deba@433: int& _compNum; deba@433: deba@433: typename Digraph::template NodeMap _numMap; deba@433: typename Digraph::template NodeMap _retMap; deba@433: typename Digraph::template NodeMap _predMap; deba@433: std::stack _edgeStack; deba@433: int _num; deba@433: }; deba@433: deba@433: deba@433: template deba@433: class BiNodeConnectedCutNodesVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Edge Edge; deba@433: deba@433: BiNodeConnectedCutNodesVisitor(const Digraph& graph, NodeMap& cutMap, deba@433: int& cutNum) deba@433: : _graph(graph), _cutMap(cutMap), _cutNum(cutNum), deba@433: _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {} deba@433: deba@433: void start(const Node& node) { deba@433: _predMap.set(node, INVALID); deba@433: rootCut = false; deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _numMap.set(node, _num); deba@433: _retMap.set(node, _num); deba@433: ++_num; deba@433: } deba@433: deba@433: void discover(const Arc& edge) { deba@433: _predMap.set(_graph.target(edge), _graph.source(edge)); deba@433: } deba@433: deba@433: void examine(const Arc& edge) { deba@433: if (_graph.source(edge) == _graph.target(edge) && deba@433: _graph.direction(edge)) { deba@433: if (!_cutMap[_graph.source(edge)]) { deba@433: _cutMap.set(_graph.source(edge), true); deba@433: ++_cutNum; deba@433: } deba@433: return; deba@433: } deba@433: if (_predMap[_graph.source(edge)] == _graph.target(edge)) return; deba@433: if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: void backtrack(const Arc& edge) { deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) { deba@433: if (_predMap[_graph.source(edge)] != INVALID) { deba@433: if (!_cutMap[_graph.source(edge)]) { deba@433: _cutMap.set(_graph.source(edge), true); deba@433: ++_cutNum; deba@433: } deba@433: } else if (rootCut) { deba@433: if (!_cutMap[_graph.source(edge)]) { deba@433: _cutMap.set(_graph.source(edge), true); deba@433: ++_cutNum; deba@433: } deba@433: } else { deba@433: rootCut = true; deba@433: } deba@433: } deba@433: } deba@433: deba@433: private: deba@433: const Digraph& _graph; deba@433: NodeMap& _cutMap; deba@433: int& _cutNum; deba@433: deba@433: typename Digraph::template NodeMap _numMap; deba@433: typename Digraph::template NodeMap _retMap; deba@433: typename Digraph::template NodeMap _predMap; deba@433: std::stack _edgeStack; deba@433: int _num; deba@433: bool rootCut; deba@433: }; deba@433: deba@433: } deba@433: deba@433: template deba@433: int countBiNodeConnectedComponents(const Graph& graph); deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Checks the graph is bi-node-connected. deba@433: /// deba@433: /// This function checks that the undirected graph is bi-node-connected deba@433: /// graph. The graph is bi-node-connected if any two undirected edge is deba@433: /// on same circle. deba@433: /// deba@433: /// \param graph The graph. kpeter@606: /// \return \c true when the graph bi-node-connected. deba@433: template deba@433: bool biNodeConnected(const Graph& graph) { deba@433: return countBiNodeConnectedComponents(graph) <= 1; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Count the biconnected components. deba@433: /// deba@433: /// This function finds the bi-node-connected components in an undirected deba@433: /// graph. The biconnected components are the classes of an equivalence deba@433: /// relation on the undirected edges. Two undirected edge is in relationship deba@433: /// when they are on same circle. deba@433: /// deba@433: /// \param graph The graph. deba@433: /// \return The number of components. deba@433: template deba@433: int countBiNodeConnectedComponents(const Graph& graph) { deba@433: checkConcept(); deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef CountBiNodeConnectedComponentsVisitor Visitor; deba@433: deba@433: int compNum = 0; deba@433: Visitor visitor(graph, compNum); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the bi-node-connected components. deba@433: /// deba@433: /// This function finds the bi-node-connected components in an undirected deba@433: /// graph. The bi-node-connected components are the classes of an equivalence deba@433: /// relation on the undirected edges. Two undirected edge are in relationship deba@433: /// when they are on same circle. deba@433: /// deba@433: /// \param graph The graph. deba@433: /// \retval compMap A writable uedge map. The values will be set from 0 deba@433: /// to the number of the biconnected components minus one. Each values deba@433: /// of the map will be set exactly once, the values of a certain component deba@433: /// will be set continuously. deba@433: /// \return The number of components. deba@433: /// deba@433: template deba@433: int biNodeConnectedComponents(const Graph& graph, deba@433: EdgeMap& compMap) { deba@433: checkConcept(); deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::Edge Edge; deba@433: checkConcept, EdgeMap>(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef BiNodeConnectedComponentsVisitor Visitor; deba@433: deba@433: int compNum = 0; deba@433: Visitor visitor(graph, compMap, compNum); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the bi-node-connected cut nodes. deba@433: /// deba@433: /// This function finds the bi-node-connected cut nodes in an undirected deba@433: /// graph. The bi-node-connected components are the classes of an equivalence deba@433: /// relation on the undirected edges. Two undirected edges are in deba@433: /// relationship when they are on same circle. The biconnected components deba@433: /// are separted by nodes which are the cut nodes of the components. deba@433: /// deba@433: /// \param graph The graph. deba@433: /// \retval cutMap A writable edge map. The values will be set true when deba@433: /// the node separate two or more components. deba@433: /// \return The number of the cut nodes. deba@433: template deba@433: int biNodeConnectedCutNodes(const Graph& graph, NodeMap& cutMap) { deba@433: checkConcept(); deba@433: typedef typename Graph::Node Node; deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: checkConcept, NodeMap>(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef BiNodeConnectedCutNodesVisitor Visitor; deba@433: deba@433: int cutNum = 0; deba@433: Visitor visitor(graph, cutMap, cutNum); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: return cutNum; deba@433: } deba@433: deba@435: namespace _connectivity_bits { deba@433: deba@433: template deba@433: class CountBiEdgeConnectedComponentsVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Edge Edge; deba@433: deba@433: CountBiEdgeConnectedComponentsVisitor(const Digraph& graph, int &compNum) deba@433: : _graph(graph), _compNum(compNum), deba@433: _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {} deba@433: deba@433: void start(const Node& node) { deba@433: _predMap.set(node, INVALID); deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _numMap.set(node, _num); deba@433: _retMap.set(node, _num); deba@433: ++_num; deba@433: } deba@433: deba@433: void leave(const Node& node) { deba@433: if (_numMap[node] <= _retMap[node]) { deba@433: ++_compNum; deba@433: } deba@433: } deba@433: deba@433: void discover(const Arc& edge) { deba@433: _predMap.set(_graph.target(edge), edge); deba@433: } deba@433: deba@433: void examine(const Arc& edge) { deba@433: if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) { deba@433: return; deba@433: } deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: void backtrack(const Arc& edge) { deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: private: deba@433: const Digraph& _graph; deba@433: int& _compNum; deba@433: deba@433: typename Digraph::template NodeMap _numMap; deba@433: typename Digraph::template NodeMap _retMap; deba@433: typename Digraph::template NodeMap _predMap; deba@433: int _num; deba@433: }; deba@433: deba@433: template deba@433: class BiEdgeConnectedComponentsVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Edge Edge; deba@433: deba@433: BiEdgeConnectedComponentsVisitor(const Digraph& graph, deba@433: NodeMap& compMap, int &compNum) deba@433: : _graph(graph), _compMap(compMap), _compNum(compNum), deba@433: _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {} deba@433: deba@433: void start(const Node& node) { deba@433: _predMap.set(node, INVALID); deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _numMap.set(node, _num); deba@433: _retMap.set(node, _num); deba@433: _nodeStack.push(node); deba@433: ++_num; deba@433: } deba@433: deba@433: void leave(const Node& node) { deba@433: if (_numMap[node] <= _retMap[node]) { deba@433: while (_nodeStack.top() != node) { deba@433: _compMap.set(_nodeStack.top(), _compNum); deba@433: _nodeStack.pop(); deba@433: } deba@433: _compMap.set(node, _compNum); deba@433: _nodeStack.pop(); deba@433: ++_compNum; deba@433: } deba@433: } deba@433: deba@433: void discover(const Arc& edge) { deba@433: _predMap.set(_graph.target(edge), edge); deba@433: } deba@433: deba@433: void examine(const Arc& edge) { deba@433: if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) { deba@433: return; deba@433: } deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: void backtrack(const Arc& edge) { deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: private: deba@433: const Digraph& _graph; deba@433: NodeMap& _compMap; deba@433: int& _compNum; deba@433: deba@433: typename Digraph::template NodeMap _numMap; deba@433: typename Digraph::template NodeMap _retMap; deba@433: typename Digraph::template NodeMap _predMap; deba@433: std::stack _nodeStack; deba@433: int _num; deba@433: }; deba@433: deba@433: deba@433: template deba@433: class BiEdgeConnectedCutEdgesVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Edge Edge; deba@433: deba@433: BiEdgeConnectedCutEdgesVisitor(const Digraph& graph, deba@433: ArcMap& cutMap, int &cutNum) deba@433: : _graph(graph), _cutMap(cutMap), _cutNum(cutNum), deba@433: _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {} deba@433: deba@433: void start(const Node& node) { deba@433: _predMap[node] = INVALID; deba@433: } deba@433: deba@433: void reach(const Node& node) { deba@433: _numMap.set(node, _num); deba@433: _retMap.set(node, _num); deba@433: ++_num; deba@433: } deba@433: deba@433: void leave(const Node& node) { deba@433: if (_numMap[node] <= _retMap[node]) { deba@433: if (_predMap[node] != INVALID) { deba@433: _cutMap.set(_predMap[node], true); deba@433: ++_cutNum; deba@433: } deba@433: } deba@433: } deba@433: deba@433: void discover(const Arc& edge) { deba@433: _predMap.set(_graph.target(edge), edge); deba@433: } deba@433: deba@433: void examine(const Arc& edge) { deba@433: if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) { deba@433: return; deba@433: } deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: void backtrack(const Arc& edge) { deba@433: if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) { deba@433: _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]); deba@433: } deba@433: } deba@433: deba@433: private: deba@433: const Digraph& _graph; deba@433: ArcMap& _cutMap; deba@433: int& _cutNum; deba@433: deba@433: typename Digraph::template NodeMap _numMap; deba@433: typename Digraph::template NodeMap _retMap; deba@433: typename Digraph::template NodeMap _predMap; deba@433: int _num; deba@433: }; deba@433: } deba@433: deba@433: template deba@433: int countBiEdgeConnectedComponents(const Graph& graph); deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Checks that the graph is bi-edge-connected. deba@433: /// deba@433: /// This function checks that the graph is bi-edge-connected. The undirected deba@433: /// graph is bi-edge-connected when any two nodes are connected with two deba@433: /// edge-disjoint paths. deba@433: /// deba@433: /// \param graph The undirected graph. deba@433: /// \return The number of components. deba@433: template deba@433: bool biEdgeConnected(const Graph& graph) { deba@433: return countBiEdgeConnectedComponents(graph) <= 1; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Count the bi-edge-connected components. deba@433: /// deba@433: /// This function count the bi-edge-connected components in an undirected deba@433: /// graph. The bi-edge-connected components are the classes of an equivalence deba@433: /// relation on the nodes. Two nodes are in relationship when they are deba@433: /// connected with at least two edge-disjoint paths. deba@433: /// deba@433: /// \param graph The undirected graph. deba@433: /// \return The number of components. deba@433: template deba@433: int countBiEdgeConnectedComponents(const Graph& graph) { deba@433: checkConcept(); deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef CountBiEdgeConnectedComponentsVisitor Visitor; deba@433: deba@433: int compNum = 0; deba@433: Visitor visitor(graph, compNum); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the bi-edge-connected components. deba@433: /// deba@433: /// This function finds the bi-edge-connected components in an undirected deba@433: /// graph. The bi-edge-connected components are the classes of an equivalence deba@433: /// relation on the nodes. Two nodes are in relationship when they are deba@433: /// connected at least two edge-disjoint paths. deba@433: /// deba@433: /// \param graph The graph. deba@433: /// \retval compMap A writable node map. The values will be set from 0 to deba@433: /// the number of the biconnected components minus one. Each values deba@433: /// of the map will be set exactly once, the values of a certain component deba@433: /// will be set continuously. deba@433: /// \return The number of components. deba@433: /// deba@433: template deba@433: int biEdgeConnectedComponents(const Graph& graph, NodeMap& compMap) { deba@433: checkConcept(); deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::Node Node; deba@433: checkConcept, NodeMap>(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef BiEdgeConnectedComponentsVisitor Visitor; deba@433: deba@433: int compNum = 0; deba@433: Visitor visitor(graph, compMap, compNum); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: return compNum; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Find the bi-edge-connected cut edges. deba@433: /// deba@433: /// This function finds the bi-edge-connected components in an undirected deba@433: /// graph. The bi-edge-connected components are the classes of an equivalence deba@433: /// relation on the nodes. Two nodes are in relationship when they are deba@433: /// connected with at least two edge-disjoint paths. The bi-edge-connected deba@433: /// components are separted by edges which are the cut edges of the deba@433: /// components. deba@433: /// deba@433: /// \param graph The graph. deba@433: /// \retval cutMap A writable node map. The values will be set true when the deba@433: /// edge is a cut edge. deba@433: /// \return The number of cut edges. deba@433: template deba@433: int biEdgeConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) { deba@433: checkConcept(); deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::Edge Edge; deba@433: checkConcept, EdgeMap>(); deba@433: deba@435: using namespace _connectivity_bits; deba@433: deba@433: typedef BiEdgeConnectedCutEdgesVisitor Visitor; deba@433: deba@433: int cutNum = 0; deba@433: Visitor visitor(graph, cutMap, cutNum); deba@433: deba@433: DfsVisit dfs(graph, visitor); deba@433: dfs.init(); deba@433: deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: return cutNum; deba@433: } deba@433: deba@433: deba@435: namespace _connectivity_bits { deba@433: deba@433: template deba@433: class TopologicalSortVisitor : public DfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::Arc edge; deba@433: deba@433: TopologicalSortVisitor(IntNodeMap& order, int num) deba@433: : _order(order), _num(num) {} deba@433: deba@433: void leave(const Node& node) { deba@433: _order.set(node, --_num); deba@433: } deba@433: deba@433: private: deba@433: IntNodeMap& _order; deba@433: int _num; deba@433: }; deba@433: deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Sort the nodes of a DAG into topolgical order. deba@433: /// deba@433: /// Sort the nodes of a DAG into topolgical order. deba@433: /// deba@433: /// \param graph The graph. It must be directed and acyclic. deba@433: /// \retval order A writable node map. The values will be set from 0 to deba@433: /// the number of the nodes in the graph minus one. Each values of the map deba@433: /// will be set exactly once, the values will be set descending order. deba@433: /// deba@433: /// \see checkedTopologicalSort deba@433: /// \see dag deba@433: template deba@433: void topologicalSort(const Digraph& graph, NodeMap& order) { deba@435: using namespace _connectivity_bits; deba@433: deba@433: checkConcept(); deba@433: checkConcept, NodeMap>(); deba@433: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: typedef typename Digraph::Arc Arc; deba@433: deba@433: TopologicalSortVisitor deba@433: visitor(order, countNodes(graph)); deba@433: deba@433: DfsVisit > deba@433: dfs(graph, visitor); deba@433: deba@433: dfs.init(); deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: dfs.start(); deba@433: } deba@433: } deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Sort the nodes of a DAG into topolgical order. deba@433: /// deba@433: /// Sort the nodes of a DAG into topolgical order. It also checks deba@433: /// that the given graph is DAG. deba@433: /// deba@444: /// \param digraph The graph. It must be directed and acyclic. deba@433: /// \retval order A readable - writable node map. The values will be set deba@433: /// from 0 to the number of the nodes in the graph minus one. Each values deba@433: /// of the map will be set exactly once, the values will be set descending deba@433: /// order. kpeter@606: /// \return \c false when the graph is not DAG. deba@433: /// deba@433: /// \see topologicalSort deba@433: /// \see dag deba@433: template deba@435: bool checkedTopologicalSort(const Digraph& digraph, NodeMap& order) { deba@435: using namespace _connectivity_bits; deba@433: deba@433: checkConcept(); deba@433: checkConcept, deba@433: NodeMap>(); deba@433: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: typedef typename Digraph::Arc Arc; deba@433: deba@435: for (NodeIt it(digraph); it != INVALID; ++it) { deba@435: order.set(it, -1); deba@435: } deba@433: deba@433: TopologicalSortVisitor deba@435: visitor(order, countNodes(digraph)); deba@433: deba@433: DfsVisit > deba@435: dfs(digraph, visitor); deba@433: deba@433: dfs.init(); deba@435: for (NodeIt it(digraph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: while (!dfs.emptyQueue()) { deba@435: Arc arc = dfs.nextArc(); deba@435: Node target = digraph.target(arc); deba@433: if (dfs.reached(target) && order[target] == -1) { deba@433: return false; deba@433: } deba@433: dfs.processNextArc(); deba@433: } deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check that the given directed graph is a DAG. deba@433: /// deba@433: /// Check that the given directed graph is a DAG. The DAG is deba@433: /// an Directed Acyclic Digraph. kpeter@606: /// \return \c false when the graph is not DAG. deba@433: /// \see acyclic deba@433: template deba@435: bool dag(const Digraph& digraph) { deba@433: deba@433: checkConcept(); deba@433: deba@433: typedef typename Digraph::Node Node; deba@433: typedef typename Digraph::NodeIt NodeIt; deba@433: typedef typename Digraph::Arc Arc; deba@433: deba@433: typedef typename Digraph::template NodeMap ProcessedMap; deba@433: deba@433: typename Dfs::template SetProcessedMap:: deba@435: Create dfs(digraph); deba@433: deba@435: ProcessedMap processed(digraph); deba@433: dfs.processedMap(processed); deba@433: deba@433: dfs.init(); deba@435: for (NodeIt it(digraph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: while (!dfs.emptyQueue()) { deba@433: Arc edge = dfs.nextArc(); deba@435: Node target = digraph.target(edge); deba@433: if (dfs.reached(target) && !processed[target]) { deba@433: return false; deba@433: } deba@433: dfs.processNextArc(); deba@433: } deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check that the given undirected graph is acyclic. deba@433: /// deba@433: /// Check that the given undirected graph acyclic. deba@433: /// \param graph The undirected graph. kpeter@606: /// \return \c true when there is no circle in the graph. deba@433: /// \see dag deba@433: template deba@433: bool acyclic(const Graph& graph) { deba@433: checkConcept(); deba@433: typedef typename Graph::Node Node; deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::Arc Arc; deba@433: Dfs dfs(graph); deba@433: dfs.init(); deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: dfs.addSource(it); deba@433: while (!dfs.emptyQueue()) { deba@433: Arc edge = dfs.nextArc(); deba@433: Node source = graph.source(edge); deba@433: Node target = graph.target(edge); deba@433: if (dfs.reached(target) && deba@433: dfs.predArc(source) != graph.oppositeArc(edge)) { deba@433: return false; deba@433: } deba@433: dfs.processNextArc(); deba@433: } deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check that the given undirected graph is tree. deba@433: /// deba@433: /// Check that the given undirected graph is tree. deba@433: /// \param graph The undirected graph. kpeter@606: /// \return \c true when the graph is acyclic and connected. deba@433: template deba@433: bool tree(const Graph& graph) { deba@433: checkConcept(); deba@433: typedef typename Graph::Node Node; deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::Arc Arc; deba@433: Dfs dfs(graph); deba@433: dfs.init(); deba@433: dfs.addSource(NodeIt(graph)); deba@433: while (!dfs.emptyQueue()) { deba@433: Arc edge = dfs.nextArc(); deba@433: Node source = graph.source(edge); deba@433: Node target = graph.target(edge); deba@433: if (dfs.reached(target) && deba@433: dfs.predArc(source) != graph.oppositeArc(edge)) { deba@433: return false; deba@433: } deba@433: dfs.processNextArc(); deba@433: } deba@433: for (NodeIt it(graph); it != INVALID; ++it) { deba@433: if (!dfs.reached(it)) { deba@433: return false; deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@435: namespace _connectivity_bits { deba@433: deba@433: template deba@433: class BipartiteVisitor : public BfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Node Node; deba@433: deba@433: BipartiteVisitor(const Digraph& graph, bool& bipartite) deba@433: : _graph(graph), _part(graph), _bipartite(bipartite) {} deba@433: deba@433: void start(const Node& node) { deba@433: _part[node] = true; deba@433: } deba@433: void discover(const Arc& edge) { deba@433: _part.set(_graph.target(edge), !_part[_graph.source(edge)]); deba@433: } deba@433: void examine(const Arc& edge) { deba@433: _bipartite = _bipartite && deba@433: _part[_graph.target(edge)] != _part[_graph.source(edge)]; deba@433: } deba@433: deba@433: private: deba@433: deba@433: const Digraph& _graph; deba@433: typename Digraph::template NodeMap _part; deba@433: bool& _bipartite; deba@433: }; deba@433: deba@433: template deba@433: class BipartitePartitionsVisitor : public BfsVisitor { deba@433: public: deba@433: typedef typename Digraph::Arc Arc; deba@433: typedef typename Digraph::Node Node; deba@433: deba@433: BipartitePartitionsVisitor(const Digraph& graph, deba@433: PartMap& part, bool& bipartite) deba@433: : _graph(graph), _part(part), _bipartite(bipartite) {} deba@433: deba@433: void start(const Node& node) { deba@433: _part.set(node, true); deba@433: } deba@433: void discover(const Arc& edge) { deba@433: _part.set(_graph.target(edge), !_part[_graph.source(edge)]); deba@433: } deba@433: void examine(const Arc& edge) { deba@433: _bipartite = _bipartite && deba@433: _part[_graph.target(edge)] != _part[_graph.source(edge)]; deba@433: } deba@433: deba@433: private: deba@433: deba@433: const Digraph& _graph; deba@433: PartMap& _part; deba@433: bool& _bipartite; deba@433: }; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check if the given undirected graph is bipartite or not deba@433: /// deba@433: /// The function checks if the given undirected \c graph graph is bipartite deba@433: /// or not. The \ref Bfs algorithm is used to calculate the result. deba@433: /// \param graph The undirected graph. kpeter@606: /// \return \c true if \c graph is bipartite, \c false otherwise. deba@433: /// \sa bipartitePartitions deba@433: template deba@433: inline bool bipartite(const Graph &graph){ deba@435: using namespace _connectivity_bits; deba@433: deba@433: checkConcept(); deba@433: deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::ArcIt ArcIt; deba@433: deba@433: bool bipartite = true; deba@433: deba@433: BipartiteVisitor deba@433: visitor(graph, bipartite); deba@433: BfsVisit > deba@433: bfs(graph, visitor); deba@433: bfs.init(); deba@433: for(NodeIt it(graph); it != INVALID; ++it) { deba@433: if(!bfs.reached(it)){ deba@433: bfs.addSource(it); deba@433: while (!bfs.emptyQueue()) { deba@433: bfs.processNextNode(); deba@433: if (!bipartite) return false; deba@433: } deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \ingroup connectivity deba@433: /// deba@433: /// \brief Check if the given undirected graph is bipartite or not deba@433: /// deba@433: /// The function checks if the given undirected graph is bipartite deba@433: /// or not. The \ref Bfs algorithm is used to calculate the result. deba@433: /// During the execution, the \c partMap will be set as the two deba@433: /// partitions of the graph. deba@433: /// \param graph The undirected graph. deba@433: /// \retval partMap A writable bool map of nodes. It will be set as the deba@433: /// two partitions of the graph. kpeter@606: /// \return \c true if \c graph is bipartite, \c false otherwise. deba@433: template deba@433: inline bool bipartitePartitions(const Graph &graph, NodeMap &partMap){ deba@435: using namespace _connectivity_bits; deba@433: deba@433: checkConcept(); deba@433: deba@433: typedef typename Graph::Node Node; deba@433: typedef typename Graph::NodeIt NodeIt; deba@433: typedef typename Graph::ArcIt ArcIt; deba@433: deba@433: bool bipartite = true; deba@433: deba@433: BipartitePartitionsVisitor deba@433: visitor(graph, partMap, bipartite); deba@433: BfsVisit > deba@433: bfs(graph, visitor); deba@433: bfs.init(); deba@433: for(NodeIt it(graph); it != INVALID; ++it) { deba@433: if(!bfs.reached(it)){ deba@433: bfs.addSource(it); deba@433: while (!bfs.emptyQueue()) { deba@433: bfs.processNextNode(); deba@433: if (!bipartite) return false; deba@433: } deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \brief Returns true when there are not loop edges in the graph. deba@433: /// deba@433: /// Returns true when there are not loop edges in the graph. deba@433: template deba@435: bool loopFree(const Digraph& digraph) { deba@435: for (typename Digraph::ArcIt it(digraph); it != INVALID; ++it) { deba@435: if (digraph.source(it) == digraph.target(it)) return false; deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \brief Returns true when there are not parallel edges in the graph. deba@433: /// deba@433: /// Returns true when there are not parallel edges in the graph. deba@433: template deba@435: bool parallelFree(const Digraph& digraph) { deba@435: typename Digraph::template NodeMap reached(digraph, false); deba@435: for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) { deba@435: for (typename Digraph::OutArcIt a(digraph, n); a != INVALID; ++a) { deba@435: if (reached[digraph.target(a)]) return false; deba@435: reached.set(digraph.target(a), true); deba@433: } deba@435: for (typename Digraph::OutArcIt a(digraph, n); a != INVALID; ++a) { deba@435: reached.set(digraph.target(a), false); deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: /// \brief Returns true when there are not loop edges and parallel deba@433: /// edges in the graph. deba@433: /// deba@433: /// Returns true when there are not loop edges and parallel edges in deba@433: /// the graph. deba@433: template deba@435: bool simpleDigraph(const Digraph& digraph) { deba@435: typename Digraph::template NodeMap reached(digraph, false); deba@435: for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) { deba@433: reached.set(n, true); deba@435: for (typename Digraph::OutArcIt a(digraph, n); a != INVALID; ++a) { deba@435: if (reached[digraph.target(a)]) return false; deba@435: reached.set(digraph.target(a), true); deba@433: } deba@435: for (typename Digraph::OutArcIt a(digraph, n); a != INVALID; ++a) { deba@435: reached.set(digraph.target(a), false); deba@433: } deba@433: reached.set(n, false); deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: } //namespace lemon deba@433: deba@435: #endif //LEMON_CONNECTIVITY_H