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@956: * Copyright (C) 2003-2010 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: kpeter@633: /// \ingroup graph_properties deba@433: /// \file deba@433: /// \brief Connectivity algorithms deba@433: /// deba@433: /// Connectivity algorithms deba@433: deba@433: namespace lemon { deba@433: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether an undirected graph is connected. deba@433: /// kpeter@695: /// This function checks whether the given undirected graph is connected, kpeter@695: /// i.e. there is a path between any two nodes in the graph. kpeter@695: /// kpeter@695: /// \return \c true if the graph is connected. deba@433: /// \note By definition, the empty graph is connected. kpeter@695: /// kpeter@695: /// \see countConnectedComponents(), connectedComponents() kpeter@695: /// \see stronglyConnected() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// deba@433: /// \brief Count the number of connected components of an undirected graph deba@433: /// kpeter@695: /// This function counts the number of connected components of the given kpeter@695: /// undirected graph. deba@433: /// kpeter@695: /// The connected components are the classes of an equivalence relation kpeter@695: /// on the nodes of an undirected graph. Two nodes are in the same class kpeter@695: /// if they are connected with a path. kpeter@695: /// kpeter@695: /// \return The number of connected components. deba@433: /// \note By definition, the empty graph consists deba@433: /// of zero connected components. kpeter@695: /// kpeter@695: /// \see connected(), connectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// deba@433: /// \brief Find the connected components of an undirected graph deba@433: /// kpeter@695: /// This function finds the connected components of the given undirected kpeter@695: /// graph. kpeter@695: /// kpeter@695: /// The connected components are the classes of an equivalence relation kpeter@695: /// on the nodes of an undirected graph. Two nodes are in the same class kpeter@695: /// if they are connected with a path. deba@433: /// kpeter@633: /// \image html connected_components.png kpeter@633: /// \image latex connected_components.eps "Connected components" width=\textwidth kpeter@633: /// kpeter@695: /// \param graph The undirected graph. deba@433: /// \retval compMap A writable node map. The values will be set from 0 to kpeter@695: /// the number of the connected components minus one. Each value of the map kpeter@695: /// will be set exactly once, and the values of a certain component will be deba@433: /// set continuously. kpeter@695: /// \return The number of connected components. kpeter@695: /// \note By definition, the empty graph consists kpeter@695: /// of zero connected components. kpeter@695: /// kpeter@695: /// \see connected(), countConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether a directed graph is strongly connected. deba@433: /// kpeter@695: /// This function checks whether the given directed graph is strongly kpeter@695: /// connected, i.e. any two nodes of the digraph are deba@433: /// connected with directed paths in both direction. deba@433: /// kpeter@695: /// \return \c true if the digraph is strongly connected. kpeter@695: /// \note By definition, the empty digraph is strongly connected. alpar@956: /// kpeter@695: /// \see countStronglyConnectedComponents(), stronglyConnectedComponents() kpeter@695: /// \see 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: kpeter@695: 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: kpeter@633: /// \ingroup graph_properties deba@433: /// alpar@956: /// \brief Count the number of strongly connected components of a kpeter@695: /// directed graph deba@433: /// kpeter@695: /// This function counts the number of strongly connected components of kpeter@695: /// the given directed graph. kpeter@695: /// deba@433: /// The strongly connected components are the classes of an kpeter@695: /// equivalence relation on the nodes of a digraph. Two nodes are in deba@433: /// the same class if they are connected with directed paths in both deba@433: /// direction. deba@433: /// kpeter@695: /// \return The number of strongly connected components. kpeter@695: /// \note By definition, the empty digraph has zero deba@433: /// strongly connected components. kpeter@695: /// kpeter@695: /// \see stronglyConnected(), stronglyConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// deba@433: /// \brief Find the strongly connected components of a directed graph deba@433: /// kpeter@695: /// This function finds the strongly connected components of the given kpeter@695: /// directed graph. In addition, the numbering of the components will kpeter@695: /// satisfy that there is no arc going from a higher numbered component kpeter@695: /// to a lower one (i.e. it provides a topological order of the components). kpeter@695: /// kpeter@695: /// The strongly connected components are the classes of an kpeter@695: /// equivalence relation on the nodes of a digraph. Two nodes are in kpeter@695: /// the same class if they are connected with directed paths in both kpeter@695: /// direction. deba@433: /// kpeter@633: /// \image html strongly_connected_components.png kpeter@633: /// \image latex strongly_connected_components.eps "Strongly connected components" width=\textwidth kpeter@633: /// 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 kpeter@695: /// of the map will be set exactly once, and the values of a certain kpeter@695: /// component will be set continuously. kpeter@695: /// \return The number of strongly connected components. kpeter@695: /// \note By definition, the empty digraph has zero kpeter@695: /// strongly connected components. kpeter@695: /// kpeter@695: /// \see stronglyConnected(), countStronglyConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// deba@433: /// \brief Find the cut arcs of the strongly connected components. deba@433: /// kpeter@695: /// This function finds the cut arcs of the strongly connected components kpeter@695: /// of the given digraph. kpeter@695: /// kpeter@695: /// The strongly connected components are the classes of an kpeter@695: /// equivalence relation on the nodes of a digraph. Two nodes are in kpeter@695: /// the same class if they are connected with directed paths in both kpeter@695: /// direction. deba@433: /// The strongly connected components are separated by the cut arcs. deba@433: /// kpeter@695: /// \param digraph The digraph. kpeter@695: /// \retval cutMap A writable arc map. The values will be set to \c true kpeter@695: /// for the cut arcs (exactly once for each cut arc), and will not be kpeter@695: /// changed for other arcs. kpeter@695: /// \return The number of cut arcs. deba@433: /// kpeter@695: /// \see stronglyConnected(), stronglyConnectedComponents() deba@433: template kpeter@695: int stronglyConnectedCutArcs(const Digraph& digraph, 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: kpeter@695: Container nodes(countNodes(digraph)); deba@433: typedef LeaveOrderVisitor Visitor; deba@433: Visitor visitor(nodes.begin()); deba@433: kpeter@695: DfsVisit dfs(digraph, visitor); deba@433: dfs.init(); kpeter@695: 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: kpeter@695: RDigraph rdigraph(digraph); deba@433: deba@433: int cutNum = 0; deba@433: deba@435: typedef StronglyConnectedCutArcsVisitor RVisitor; kpeter@695: RVisitor rvisitor(rdigraph, cutMap, cutNum); deba@433: kpeter@695: 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: } 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether an undirected graph is bi-node-connected. deba@433: /// alpar@956: /// This function checks whether the given undirected graph is kpeter@695: /// bi-node-connected, i.e. any two edges are on same circle. deba@433: /// kpeter@695: /// \return \c true if the graph bi-node-connected. kpeter@695: /// \note By definition, the empty graph is bi-node-connected. kpeter@695: /// kpeter@695: /// \see countBiNodeConnectedComponents(), biNodeConnectedComponents() deba@433: template deba@433: bool biNodeConnected(const Graph& graph) { deba@433: return countBiNodeConnectedComponents(graph) <= 1; deba@433: } deba@433: kpeter@633: /// \ingroup graph_properties deba@433: /// alpar@956: /// \brief Count the number of bi-node-connected components of an kpeter@695: /// undirected graph. deba@433: /// kpeter@695: /// This function counts the number of bi-node-connected components of kpeter@695: /// the given undirected graph. deba@433: /// kpeter@695: /// The bi-node-connected components are the classes of an equivalence kpeter@695: /// relation on the edges of a undirected graph. Two edges are in the kpeter@695: /// same class if they are on same circle. kpeter@695: /// kpeter@695: /// \return The number of bi-node-connected components. kpeter@695: /// kpeter@695: /// \see biNodeConnected(), biNodeConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Find the bi-node-connected components of an undirected graph. deba@433: /// kpeter@695: /// This function finds the bi-node-connected components of the given kpeter@695: /// undirected graph. kpeter@695: /// kpeter@695: /// The bi-node-connected components are the classes of an equivalence kpeter@695: /// relation on the edges of a undirected graph. Two edges are in the kpeter@695: /// same class if they are on same circle. deba@433: /// kpeter@633: /// \image html node_biconnected_components.png kpeter@633: /// \image latex node_biconnected_components.eps "bi-node-connected components" width=\textwidth kpeter@633: /// kpeter@695: /// \param graph The undirected graph. kpeter@695: /// \retval compMap A writable edge map. The values will be set from 0 kpeter@695: /// to the number of the bi-node-connected components minus one. Each alpar@956: /// value of the map will be set exactly once, and the values of a kpeter@695: /// certain component will be set continuously. kpeter@695: /// \return The number of bi-node-connected components. kpeter@695: /// kpeter@695: /// \see biNodeConnected(), countBiNodeConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Find the bi-node-connected cut nodes in an undirected graph. deba@433: /// kpeter@695: /// This function finds the bi-node-connected cut nodes in the given kpeter@695: /// undirected graph. deba@433: /// kpeter@695: /// The bi-node-connected components are the classes of an equivalence kpeter@695: /// relation on the edges of a undirected graph. Two edges are in the kpeter@695: /// same class if they are on same circle. kpeter@695: /// The bi-node-connected components are separted by the cut nodes of kpeter@695: /// the components. kpeter@695: /// kpeter@695: /// \param graph The undirected graph. alpar@956: /// \retval cutMap A writable node map. The values will be set to kpeter@695: /// \c true for the nodes that separate two or more components kpeter@695: /// (exactly once for each cut node), and will not be changed for kpeter@695: /// other nodes. deba@433: /// \return The number of the cut nodes. kpeter@695: /// kpeter@695: /// \see biNodeConnected(), biNodeConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether an undirected graph is bi-edge-connected. deba@433: /// alpar@956: /// This function checks whether the given undirected graph is kpeter@695: /// bi-edge-connected, i.e. any two nodes are connected with at least kpeter@695: /// two edge-disjoint paths. deba@433: /// kpeter@695: /// \return \c true if the graph is bi-edge-connected. kpeter@695: /// \note By definition, the empty graph is bi-edge-connected. kpeter@695: /// kpeter@695: /// \see countBiEdgeConnectedComponents(), biEdgeConnectedComponents() deba@433: template deba@433: bool biEdgeConnected(const Graph& graph) { deba@433: return countBiEdgeConnectedComponents(graph) <= 1; deba@433: } deba@433: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Count the number of bi-edge-connected components of an kpeter@695: /// undirected graph. deba@433: /// kpeter@695: /// This function counts the number of bi-edge-connected components of kpeter@695: /// the given undirected graph. deba@433: /// kpeter@695: /// The bi-edge-connected components are the classes of an equivalence kpeter@695: /// relation on the nodes of an undirected graph. Two nodes are in the kpeter@695: /// same class if they are connected with at least two edge-disjoint kpeter@695: /// paths. kpeter@695: /// kpeter@695: /// \return The number of bi-edge-connected components. kpeter@695: /// kpeter@695: /// \see biEdgeConnected(), biEdgeConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Find the bi-edge-connected components of an undirected graph. deba@433: /// kpeter@695: /// This function finds the bi-edge-connected components of the given kpeter@695: /// undirected graph. kpeter@695: /// kpeter@695: /// The bi-edge-connected components are the classes of an equivalence kpeter@695: /// relation on the nodes of an undirected graph. Two nodes are in the kpeter@695: /// same class if they are connected with at least two edge-disjoint kpeter@695: /// paths. deba@433: /// kpeter@633: /// \image html edge_biconnected_components.png kpeter@633: /// \image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth kpeter@633: /// kpeter@695: /// \param graph The undirected graph. deba@433: /// \retval compMap A writable node map. The values will be set from 0 to kpeter@695: /// the number of the bi-edge-connected components minus one. Each value kpeter@695: /// of the map will be set exactly once, and the values of a certain kpeter@695: /// component will be set continuously. kpeter@695: /// \return The number of bi-edge-connected components. kpeter@695: /// kpeter@695: /// \see biEdgeConnected(), countBiEdgeConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Find the bi-edge-connected cut edges in an undirected graph. deba@433: /// kpeter@695: /// This function finds the bi-edge-connected cut edges in the given alpar@956: /// undirected graph. deba@433: /// kpeter@695: /// The bi-edge-connected components are the classes of an equivalence kpeter@695: /// relation on the nodes of an undirected graph. Two nodes are in the kpeter@695: /// same class if they are connected with at least two edge-disjoint kpeter@695: /// paths. kpeter@695: /// The bi-edge-connected components are separted by the cut edges of kpeter@695: /// the components. kpeter@695: /// kpeter@695: /// \param graph The undirected graph. kpeter@695: /// \retval cutMap A writable edge map. The values will be set to \c true kpeter@695: /// for the cut edges (exactly once for each cut edge), and will not be kpeter@695: /// changed for other edges. deba@433: /// \return The number of cut edges. kpeter@695: /// kpeter@695: /// \see biEdgeConnected(), biEdgeConnectedComponents() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether a digraph is DAG. kpeter@695: /// kpeter@695: /// This function checks whether the given digraph is DAG, i.e. kpeter@695: /// \e Directed \e Acyclic \e Graph. kpeter@695: /// \return \c true if there is no directed cycle in the digraph. kpeter@695: /// \see acyclic() kpeter@695: template kpeter@695: bool dag(const Digraph& digraph) { kpeter@695: kpeter@695: checkConcept(); kpeter@695: kpeter@695: typedef typename Digraph::Node Node; kpeter@695: typedef typename Digraph::NodeIt NodeIt; kpeter@695: typedef typename Digraph::Arc Arc; kpeter@695: kpeter@695: typedef typename Digraph::template NodeMap ProcessedMap; kpeter@695: kpeter@695: typename Dfs::template SetProcessedMap:: kpeter@695: Create dfs(digraph); kpeter@695: kpeter@695: ProcessedMap processed(digraph); kpeter@695: dfs.processedMap(processed); kpeter@695: kpeter@695: dfs.init(); kpeter@695: for (NodeIt it(digraph); it != INVALID; ++it) { kpeter@695: if (!dfs.reached(it)) { kpeter@695: dfs.addSource(it); kpeter@695: while (!dfs.emptyQueue()) { kpeter@695: Arc arc = dfs.nextArc(); kpeter@695: Node target = digraph.target(arc); kpeter@695: if (dfs.reached(target) && !processed[target]) { kpeter@695: return false; kpeter@695: } kpeter@695: dfs.processNextArc(); kpeter@695: } kpeter@695: } kpeter@695: } kpeter@695: return true; kpeter@695: } kpeter@695: kpeter@695: /// \ingroup graph_properties kpeter@695: /// deba@433: /// \brief Sort the nodes of a DAG into topolgical order. deba@433: /// kpeter@695: /// This function sorts the nodes of the given acyclic digraph (DAG) kpeter@695: /// into topolgical order. deba@433: /// kpeter@695: /// \param digraph The digraph, which must be DAG. deba@433: /// \retval order A writable node map. The values will be set from 0 to kpeter@695: /// the number of the nodes in the digraph minus one. Each value of the kpeter@695: /// map will be set exactly once, and the values will be set descending kpeter@695: /// order. deba@433: /// kpeter@695: /// \see dag(), checkedTopologicalSort() deba@433: template kpeter@695: void topologicalSort(const Digraph& digraph, 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 kpeter@695: visitor(order, countNodes(digraph)); deba@433: deba@433: DfsVisit > kpeter@695: dfs(digraph, visitor); deba@433: deba@433: dfs.init(); kpeter@695: 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: kpeter@633: /// \ingroup graph_properties deba@433: /// deba@433: /// \brief Sort the nodes of a DAG into topolgical order. deba@433: /// kpeter@695: /// This function sorts the nodes of the given acyclic digraph (DAG) kpeter@695: /// into topolgical order and also checks whether the given digraph kpeter@695: /// is DAG. deba@433: /// kpeter@695: /// \param digraph The digraph. kpeter@695: /// \retval order A readable and writable node map. The values will be alpar@956: /// set from 0 to the number of the nodes in the digraph minus one. kpeter@695: /// Each value of the map will be set exactly once, and the values will kpeter@695: /// be set descending order. kpeter@695: /// \return \c false if the digraph is not DAG. deba@433: /// kpeter@695: /// \see dag(), topologicalSort() 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether an undirected graph is acyclic. deba@433: /// kpeter@695: /// This function checks whether the given undirected graph is acyclic. kpeter@695: /// \return \c true if there is no cycle in the graph. kpeter@695: /// \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()) { kpeter@695: Arc arc = dfs.nextArc(); kpeter@695: Node source = graph.source(arc); kpeter@695: Node target = graph.target(arc); deba@433: if (dfs.reached(target) && kpeter@695: dfs.predArc(source) != graph.oppositeArc(arc)) { deba@433: return false; deba@433: } deba@433: dfs.processNextArc(); deba@433: } deba@433: } deba@433: } deba@433: return true; deba@433: } deba@433: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether an undirected graph is tree. deba@433: /// kpeter@695: /// This function checks whether the given undirected graph is tree. kpeter@695: /// \return \c true if the graph is acyclic and connected. kpeter@695: /// \see acyclic(), 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; kpeter@694: if (NodeIt(graph) == INVALID) return true; deba@433: Dfs dfs(graph); deba@433: dfs.init(); deba@433: dfs.addSource(NodeIt(graph)); deba@433: while (!dfs.emptyQueue()) { kpeter@695: Arc arc = dfs.nextArc(); kpeter@695: Node source = graph.source(arc); kpeter@695: Node target = graph.target(arc); deba@433: if (dfs.reached(target) && kpeter@695: dfs.predArc(source) != graph.oppositeArc(arc)) { 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether an undirected graph is bipartite. deba@433: /// kpeter@695: /// The function checks whether the given undirected graph is bipartite. kpeter@695: /// \return \c true if the graph is bipartite. kpeter@695: /// kpeter@695: /// \see bipartitePartitions() deba@433: template kpeter@695: 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: kpeter@633: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Find the bipartite partitions of an undirected graph. deba@433: /// kpeter@695: /// This function checks whether the given undirected graph is bipartite kpeter@695: /// and gives back the bipartite partitions. kpeter@633: /// kpeter@633: /// \image html bipartite_partitions.png kpeter@633: /// \image latex bipartite_partitions.eps "Bipartite partititions" width=\textwidth kpeter@633: /// deba@433: /// \param graph The undirected graph. kpeter@695: /// \retval partMap A writable node map of \c bool (or convertible) value kpeter@695: /// type. The values will be set to \c true for one component and kpeter@695: /// \c false for the other one. kpeter@695: /// \return \c true if the graph is bipartite, \c false otherwise. kpeter@695: /// kpeter@695: /// \see bipartite() deba@433: template kpeter@695: bool bipartitePartitions(const Graph &graph, NodeMap &partMap){ deba@435: using namespace _connectivity_bits; deba@433: deba@433: checkConcept(); kpeter@695: checkConcept, NodeMap>(); 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: kpeter@695: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether the given graph contains no loop arcs/edges. kpeter@695: /// kpeter@695: /// This function returns \c true if there are no loop arcs/edges in kpeter@695: /// the given graph. It works for both directed and undirected graphs. kpeter@695: template kpeter@695: bool loopFree(const Graph& graph) { kpeter@695: for (typename Graph::ArcIt it(graph); it != INVALID; ++it) { kpeter@695: if (graph.source(it) == graph.target(it)) return false; deba@433: } deba@433: return true; deba@433: } deba@433: kpeter@695: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether the given graph contains no parallel arcs/edges. kpeter@695: /// kpeter@695: /// This function returns \c true if there are no parallel arcs/edges in kpeter@695: /// the given graph. It works for both directed and undirected graphs. kpeter@694: template kpeter@694: bool parallelFree(const Graph& graph) { kpeter@694: typename Graph::template NodeMap reached(graph, 0); kpeter@694: int cnt = 1; kpeter@694: for (typename Graph::NodeIt n(graph); n != INVALID; ++n) { kpeter@694: for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) { kpeter@694: if (reached[graph.target(a)] == cnt) return false; kpeter@694: reached[graph.target(a)] = cnt; deba@433: } kpeter@694: ++cnt; deba@433: } deba@433: return true; deba@433: } deba@433: kpeter@695: /// \ingroup graph_properties deba@433: /// kpeter@695: /// \brief Check whether the given graph is simple. kpeter@695: /// kpeter@695: /// This function returns \c true if the given graph is simple, i.e. kpeter@695: /// it contains no loop arcs/edges and no parallel arcs/edges. kpeter@695: /// The function works for both directed and undirected graphs. kpeter@695: /// \see loopFree(), parallelFree() kpeter@694: template kpeter@694: bool simpleGraph(const Graph& graph) { kpeter@694: typename Graph::template NodeMap reached(graph, 0); kpeter@694: int cnt = 1; kpeter@694: for (typename Graph::NodeIt n(graph); n != INVALID; ++n) { kpeter@694: reached[n] = cnt; kpeter@694: for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) { kpeter@694: if (reached[graph.target(a)] == cnt) return false; kpeter@694: reached[graph.target(a)] = cnt; deba@433: } kpeter@694: ++cnt; deba@433: } deba@433: return true; deba@433: } deba@433: deba@433: } //namespace lemon deba@433: deba@435: #endif //LEMON_CONNECTIVITY_H