2 * lemon/topology.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef LEMON_TOPOLOGY_H
18 #define LEMON_TOPOLOGY_H
20 #include <lemon/dfs.h>
21 #include <lemon/bfs.h>
22 #include <lemon/graph_utils.h>
23 #include <lemon/graph_adaptor.h>
24 #include <lemon/maps.h>
26 #include <lemon/concept/graph.h>
27 #include <lemon/concept/undir_graph.h>
28 #include <lemon/concept_check.h>
30 #include <lemon/bin_heap.h>
31 #include <lemon/linear_heap.h>
38 /// \brief Topology related algorithms
40 /// Topology related algorithms
46 /// \brief Check that the given undirected graph is connected.
48 /// Check that the given undirected graph connected.
49 /// \param graph The undirected graph.
50 /// \return %True when there is path between any two nodes in the graph.
51 /// \warning The empty graph is not connected.
52 template <typename UndirGraph>
53 bool connected(const UndirGraph& graph) {
54 checkConcept<concept::UndirGraph, UndirGraph>();
55 typedef typename UndirGraph::NodeIt NodeIt;
56 if (NodeIt(graph) == INVALID) return false;
57 Dfs<UndirGraph> dfs(graph);
58 dfs.run(NodeIt(graph));
59 for (NodeIt it(graph); it != INVALID; ++it) {
60 if (!dfs.reached(it)) {
69 /// \brief Count the number of connected components of an undirected graph
71 /// Count the number of connected components of an undirected graph
73 /// \param g The graph. In must be undirected.
74 /// \return The number of components
75 template <typename UndirGraph>
76 int countConnectedComponents(const UndirGraph &graph) {
77 checkConcept<concept::UndirGraph, UndirGraph>();
78 typedef typename UndirGraph::Node Node;
79 typedef typename UndirGraph::Edge Edge;
81 typedef NullMap<Node, Edge> PredMap;
82 typedef NullMap<Node, int> DistMap;
85 typename Bfs<UndirGraph>::
86 template DefPredMap<PredMap>::
87 template DefDistMap<DistMap>::
97 for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
98 if (!bfs.reached(n)) {
107 /// \ingroup topology
109 /// \brief Find the connected components of an undirected graph
111 /// Find the connected components of an undirected graph.
113 /// \param g The graph. In must be undirected.
114 /// \retval comp A writable node map. The values will be set from 0 to
115 /// the number of the connected components minus one. Each values of the map
116 /// will be set exactly once, the values of a certain component will be
117 /// set continuously.
118 /// \return The number of components
119 template <class UndirGraph, class NodeMap>
120 int connectedComponents(const UndirGraph &graph, NodeMap &compMap) {
121 checkConcept<concept::UndirGraph, UndirGraph>();
122 typedef typename UndirGraph::Node Node;
123 typedef typename UndirGraph::Edge Edge;
124 checkConcept<concept::WriteMap<Node, int>, NodeMap>();
126 typedef NullMap<Node, Edge> PredMap;
127 typedef NullMap<Node, int> DistMap;
130 typename Bfs<UndirGraph>::
131 template DefPredMap<PredMap>::
132 template DefDistMap<DistMap>::
136 bfs.predMap(predMap);
139 bfs.distMap(distMap);
142 for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
143 if(!bfs.reached(n)) {
145 while (!bfs.emptyQueue()) {
146 compMap.set(bfs.nextNode(), compNum);
147 bfs.processNextNode();
155 namespace _topology_bits {
157 template <typename Graph, typename Iterator >
158 struct LeaveOrderVisitor : public DfsVisitor<Graph> {
160 typedef typename Graph::Node Node;
161 LeaveOrderVisitor(Iterator it) : _it(it) {}
163 void leave(const Node& node) {
171 template <typename Graph, typename Map>
172 struct FillMapVisitor : public DfsVisitor<Graph> {
174 typedef typename Graph::Node Node;
175 typedef typename Map::Value Value;
177 FillMapVisitor(Map& map, Value& value)
178 : _map(map), _value(value) {}
180 void reach(const Node& node) {
181 _map.set(node, _value);
188 template <typename Graph, typename EdgeMap>
189 struct StronglyConnectedCutEdgesVisitor : public DfsVisitor<Graph> {
191 typedef typename Graph::Node Node;
192 typedef typename Graph::Edge Edge;
194 StronglyConnectedCutEdgesVisitor(const Graph& graph, EdgeMap& cutMap,
196 : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
197 _compMap(graph), _num(0) {
200 void stop(const Node&) {
204 void reach(const Node& node) {
205 _compMap.set(node, _num);
208 void examine(const Edge& edge) {
209 if (_compMap[_graph.source(edge)] != _compMap[_graph.target(edge)]) {
210 _cutMap.set(edge, true);
219 typename Graph::template NodeMap<int> _compMap;
226 /// \ingroup topology
228 /// \brief Check that the given directed graph is strongly connected.
230 /// Check that the given directed graph is strongly connected. The
231 /// graph is strongly connected when any two nodes of the graph are
232 /// connected with directed pathes in both direction.
233 /// \return %False when the graph is not strongly connected.
236 /// \waning Empty graph is not strongly connected.
237 template <typename Graph>
238 bool stronglyConnected(const Graph& graph) {
239 checkConcept<concept::StaticGraph, Graph>();
240 if (NodeIt(graph) == INVALID) return false;
242 typedef typename Graph::Node Node;
243 typedef typename Graph::NodeIt NodeIt;
245 using namespace _topology_bits;
247 typedef DfsVisitor<Graph> Visitor;
250 DfsVisit<Graph, Visitor> dfs(graph, visitor);
252 dfs.addSource(NodeIt(graph));
255 for (NodeIt it(graph); it != INVALID; ++it) {
256 if (!dfs.reached(it)) {
261 typedef RevGraphAdaptor<const Graph> RGraph;
262 RGraph rgraph(graph);
264 typedef DfsVisitor<Graph> RVisitor;
267 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
269 rdfs.addSource(NodeIt(graph));
272 for (NodeIt it(graph); it != INVALID; ++it) {
273 if (!rdfs.reached(it)) {
281 /// \ingroup topology
283 /// \brief Count the strongly connected components of a directed graph
285 /// Count the strongly connected components of a directed graph.
286 /// The strongly connected components are the classes of an equivalence
287 /// relation on the nodes of the graph. Two nodes are connected with
288 /// directed paths in both direction.
290 /// \param g The graph.
291 /// \return The number of components
292 template <typename Graph>
293 int countStronglyConnectedComponents(const Graph& graph) {
294 checkConcept<concept::StaticGraph, Graph>();
296 using namespace _topology_bits;
298 typedef typename Graph::Node Node;
299 typedef typename Graph::Edge Edge;
300 typedef typename Graph::NodeIt NodeIt;
301 typedef typename Graph::EdgeIt EdgeIt;
303 typedef std::vector<Node> Container;
304 typedef typename Container::iterator Iterator;
306 Container nodes(countNodes(graph));
307 typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
308 Visitor visitor(nodes.begin());
310 DfsVisit<Graph, Visitor> dfs(graph, visitor);
312 for (NodeIt it(graph); it != INVALID; ++it) {
313 if (!dfs.reached(it)) {
319 typedef typename Container::reverse_iterator RIterator;
320 typedef RevGraphAdaptor<const Graph> RGraph;
322 RGraph rgraph(graph);
324 typedef DfsVisitor<Graph> RVisitor;
327 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
332 for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
333 if (!rdfs.reached(*it)) {
342 /// \ingroup topology
344 /// \brief Find the strongly connected components of a directed graph
346 /// Find the strongly connected components of a directed graph.
347 /// The strongly connected components are the classes of an equivalence
348 /// relation on the nodes of the graph. Two nodes are in relationship
349 /// when there are directed paths between them in both direction.
351 /// \param g The graph.
352 /// \retval comp A writable node map. The values will be set from 0 to
353 /// the number of the strongly connected components minus one. Each values
354 /// of the map will be set exactly once, the values of a certain component
355 /// will be set continuously.
356 /// \return The number of components
357 template <typename Graph, typename NodeMap>
358 int stronglyConnectedComponents(const Graph& graph, NodeMap& compMap) {
359 checkConcept<concept::StaticGraph, Graph>();
360 typedef typename Graph::Node Node;
361 typedef typename Graph::NodeIt NodeIt;
362 checkConcept<concept::WriteMap<Node, int>, NodeMap>();
364 using namespace _topology_bits;
366 typedef std::vector<Node> Container;
367 typedef typename Container::iterator Iterator;
369 Container nodes(countNodes(graph));
370 typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
371 Visitor visitor(nodes.begin());
373 DfsVisit<Graph, Visitor> dfs(graph, visitor);
375 for (NodeIt it(graph); it != INVALID; ++it) {
376 if (!dfs.reached(it)) {
382 typedef typename Container::reverse_iterator RIterator;
383 typedef RevGraphAdaptor<const Graph> RGraph;
385 RGraph rgraph(graph);
389 typedef FillMapVisitor<RGraph, NodeMap> RVisitor;
390 RVisitor rvisitor(compMap, compNum);
392 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
395 for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
396 if (!rdfs.reached(*it)) {
405 /// \ingroup topology
407 /// \brief Find the cut edges of the strongly connected components.
409 /// Find the cut edges of the strongly connected components.
410 /// The strongly connected components are the classes of an equivalence
411 /// relation on the nodes of the graph. Two nodes are in relationship
412 /// when there are directed paths between them in both direction.
413 /// The strongly connected components are separated by the cut edges.
415 /// \param g The graph.
416 /// \retval comp A writable edge map. The values will be set true when
417 /// the edge is cut edge otherwise false.
419 /// \return The number of cut edges
420 template <typename Graph, typename EdgeMap>
421 int stronglyConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
422 checkConcept<concept::StaticGraph, Graph>();
423 typedef typename Graph::Node Node;
424 typedef typename Graph::Edge Edge;
425 typedef typename Graph::NodeIt NodeIt;
426 checkConcept<concept::WriteMap<Edge, bool>, EdgeMap>();
428 using namespace _topology_bits;
430 typedef std::vector<Node> Container;
431 typedef typename Container::iterator Iterator;
433 Container nodes(countNodes(graph));
434 typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
435 Visitor visitor(nodes.begin());
437 DfsVisit<Graph, Visitor> dfs(graph, visitor);
439 for (NodeIt it(graph); it != INVALID; ++it) {
440 if (!dfs.reached(it)) {
446 typedef typename Container::reverse_iterator RIterator;
447 typedef RevGraphAdaptor<const Graph> RGraph;
449 RGraph rgraph(graph);
453 typedef StronglyConnectedCutEdgesVisitor<RGraph, EdgeMap> RVisitor;
454 RVisitor rvisitor(rgraph, cutMap, cutNum);
456 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
459 for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
460 if (!rdfs.reached(*it)) {
468 namespace _topology_bits {
470 template <typename Graph>
471 class CountNodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
473 typedef typename Graph::Node Node;
474 typedef typename Graph::Edge Edge;
475 typedef typename Graph::UndirEdge UndirEdge;
477 CountNodeBiconnectedComponentsVisitor(const Graph& graph, int &compNum)
478 : _graph(graph), _compNum(compNum),
479 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
481 void start(const Node& node) {
482 _predMap.set(node, INVALID);
485 void reach(const Node& node) {
486 _numMap.set(node, _num);
487 _retMap.set(node, _num);
491 void discover(const Edge& edge) {
492 _predMap.set(_graph.target(edge), _graph.source(edge));
495 void examine(const Edge& edge) {
496 if (_graph.source(edge) == _graph.target(edge) &&
497 _graph.direction(edge)) {
501 if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
504 if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
505 _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
509 void backtrack(const Edge& edge) {
510 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
511 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
513 if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
522 typename Graph::template NodeMap<int> _numMap;
523 typename Graph::template NodeMap<int> _retMap;
524 typename Graph::template NodeMap<Node> _predMap;
528 template <typename Graph, typename EdgeMap>
529 class NodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
531 typedef typename Graph::Node Node;
532 typedef typename Graph::Edge Edge;
533 typedef typename Graph::UndirEdge UndirEdge;
535 NodeBiconnectedComponentsVisitor(const Graph& graph,
536 EdgeMap& compMap, int &compNum)
537 : _graph(graph), _compMap(compMap), _compNum(compNum),
538 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
540 void start(const Node& node) {
541 _predMap.set(node, INVALID);
544 void reach(const Node& node) {
545 _numMap.set(node, _num);
546 _retMap.set(node, _num);
550 void discover(const Edge& edge) {
551 Node target = _graph.target(edge);
552 _predMap.set(target, edge);
553 _edgeStack.push(edge);
556 void examine(const Edge& edge) {
557 Node source = _graph.source(edge);
558 Node target = _graph.target(edge);
559 if (source == target && _graph.direction(edge)) {
560 _compMap.set(edge, _compNum);
564 if (_numMap[target] < _numMap[source]) {
565 if (_predMap[source] != _graph.oppositeEdge(edge)) {
566 _edgeStack.push(edge);
569 if (_predMap[source] != INVALID &&
570 target == _graph.source(_predMap[source])) {
573 if (_retMap[source] > _numMap[target]) {
574 _retMap.set(source, _numMap[target]);
578 void backtrack(const Edge& edge) {
579 Node source = _graph.source(edge);
580 Node target = _graph.target(edge);
581 if (_retMap[source] > _retMap[target]) {
582 _retMap.set(source, _retMap[target]);
584 if (_numMap[source] <= _retMap[target]) {
585 while (_edgeStack.top() != edge) {
586 _compMap.set(_edgeStack.top(), _compNum);
589 _compMap.set(edge, _compNum);
600 typename Graph::template NodeMap<int> _numMap;
601 typename Graph::template NodeMap<int> _retMap;
602 typename Graph::template NodeMap<Edge> _predMap;
603 std::stack<UndirEdge> _edgeStack;
608 template <typename Graph, typename NodeMap>
609 class NodeBiconnectedCutNodesVisitor : public DfsVisitor<Graph> {
611 typedef typename Graph::Node Node;
612 typedef typename Graph::Edge Edge;
613 typedef typename Graph::UndirEdge UndirEdge;
615 NodeBiconnectedCutNodesVisitor(const Graph& graph, NodeMap& cutMap,
617 : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
618 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
620 void start(const Node& node) {
621 _predMap.set(node, INVALID);
625 void reach(const Node& node) {
626 _numMap.set(node, _num);
627 _retMap.set(node, _num);
631 void discover(const Edge& edge) {
632 _predMap.set(_graph.target(edge), _graph.source(edge));
635 void examine(const Edge& edge) {
636 if (_graph.source(edge) == _graph.target(edge) &&
637 _graph.direction(edge)) {
638 if (!_cutMap[_graph.source(edge)]) {
639 _cutMap.set(_graph.source(edge), true);
644 if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
645 if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
646 _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
650 void backtrack(const Edge& edge) {
651 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
652 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
654 if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
655 if (_predMap[_graph.source(edge)] != INVALID) {
656 if (!_cutMap[_graph.source(edge)]) {
657 _cutMap.set(_graph.source(edge), true);
660 } else if (rootCut) {
661 if (!_cutMap[_graph.source(edge)]) {
662 _cutMap.set(_graph.source(edge), true);
676 typename Graph::template NodeMap<int> _numMap;
677 typename Graph::template NodeMap<int> _retMap;
678 typename Graph::template NodeMap<Node> _predMap;
679 std::stack<UndirEdge> _edgeStack;
686 template <typename UndirGraph>
687 int countNodeBiconnectedComponents(const UndirGraph& graph);
689 /// \ingroup topology
691 /// \brief Checks the graph is node biconnected.
693 /// This function checks that the undirected graph is node biconnected
694 /// graph. The graph is node biconnected if any two undirected edge is
697 /// \param graph The graph.
698 /// \return %True when the graph node biconnected.
699 /// \todo Make it faster.
700 template <typename UndirGraph>
701 bool nodeBiconnected(const UndirGraph& graph) {
702 return countNodeBiconnectedComponents(graph) == 1;
705 /// \ingroup topology
707 /// \brief Count the biconnected components.
709 /// This function finds the node biconnected components in an undirected
710 /// graph. The biconnected components are the classes of an equivalence
711 /// relation on the undirected edges. Two undirected edge is in relationship
712 /// when they are on same circle.
714 /// \param graph The graph.
715 /// \return The number of components.
716 template <typename UndirGraph>
717 int countNodeBiconnectedComponents(const UndirGraph& graph) {
718 checkConcept<concept::UndirGraph, UndirGraph>();
719 typedef typename UndirGraph::NodeIt NodeIt;
721 using namespace _topology_bits;
723 typedef CountNodeBiconnectedComponentsVisitor<UndirGraph> Visitor;
726 Visitor visitor(graph, compNum);
728 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
731 for (NodeIt it(graph); it != INVALID; ++it) {
732 if (!dfs.reached(it)) {
740 /// \ingroup topology
742 /// \brief Find the node biconnected components.
744 /// This function finds the node biconnected components in an undirected
745 /// graph. The node biconnected components are the classes of an equivalence
746 /// relation on the undirected edges. Two undirected edge are in relationship
747 /// when they are on same circle.
749 /// \param graph The graph.
750 /// \retval comp A writable undir edge map. The values will be set from 0 to
751 /// the number of the biconnected components minus one. Each values
752 /// of the map will be set exactly once, the values of a certain component
753 /// will be set continuously.
754 /// \return The number of components.
755 template <typename UndirGraph, typename UndirEdgeMap>
756 int nodeBiconnectedComponents(const UndirGraph& graph,
757 UndirEdgeMap& compMap) {
758 checkConcept<concept::UndirGraph, UndirGraph>();
759 typedef typename UndirGraph::NodeIt NodeIt;
760 typedef typename UndirGraph::UndirEdge UndirEdge;
761 checkConcept<concept::WriteMap<UndirEdge, int>, UndirEdgeMap>();
763 using namespace _topology_bits;
765 typedef NodeBiconnectedComponentsVisitor<UndirGraph, UndirEdgeMap> Visitor;
768 Visitor visitor(graph, compMap, compNum);
770 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
773 for (NodeIt it(graph); it != INVALID; ++it) {
774 if (!dfs.reached(it)) {
782 /// \ingroup topology
784 /// \brief Find the node biconnected cut nodes.
786 /// This function finds the node biconnected cut nodes in an undirected
787 /// graph. The node biconnected components are the classes of an equivalence
788 /// relation on the undirected edges. Two undirected edges are in
789 /// relationship when they are on same circle. The biconnected components
790 /// are separted by nodes which are the cut nodes of the components.
792 /// \param graph The graph.
793 /// \retval comp A writable edge map. The values will be set true when
794 /// the node separate two or more components.
795 /// \return The number of the cut nodes.
796 template <typename UndirGraph, typename NodeMap>
797 int nodeBiconnectedCutNodes(const UndirGraph& graph, NodeMap& cutMap) {
798 checkConcept<concept::UndirGraph, UndirGraph>();
799 typedef typename UndirGraph::Node Node;
800 typedef typename UndirGraph::NodeIt NodeIt;
801 checkConcept<concept::WriteMap<Node, bool>, NodeMap>();
803 using namespace _topology_bits;
805 typedef NodeBiconnectedCutNodesVisitor<UndirGraph, NodeMap> Visitor;
808 Visitor visitor(graph, cutMap, cutNum);
810 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
813 for (NodeIt it(graph); it != INVALID; ++it) {
814 if (!dfs.reached(it)) {
822 namespace _topology_bits {
824 template <typename Graph>
825 class CountEdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
827 typedef typename Graph::Node Node;
828 typedef typename Graph::Edge Edge;
829 typedef typename Graph::UndirEdge UndirEdge;
831 CountEdgeBiconnectedComponentsVisitor(const Graph& graph, int &compNum)
832 : _graph(graph), _compNum(compNum),
833 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
835 void start(const Node& node) {
836 _predMap.set(node, INVALID);
839 void reach(const Node& node) {
840 _numMap.set(node, _num);
841 _retMap.set(node, _num);
845 void leave(const Node& node) {
846 if (_numMap[node] <= _retMap[node]) {
851 void discover(const Edge& edge) {
852 _predMap.set(_graph.target(edge), edge);
855 void examine(const Edge& edge) {
856 if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
859 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
860 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
864 void backtrack(const Edge& edge) {
865 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
866 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
874 typename Graph::template NodeMap<int> _numMap;
875 typename Graph::template NodeMap<int> _retMap;
876 typename Graph::template NodeMap<Edge> _predMap;
880 template <typename Graph, typename NodeMap>
881 class EdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
883 typedef typename Graph::Node Node;
884 typedef typename Graph::Edge Edge;
885 typedef typename Graph::UndirEdge UndirEdge;
887 EdgeBiconnectedComponentsVisitor(const Graph& graph,
888 NodeMap& compMap, int &compNum)
889 : _graph(graph), _compMap(compMap), _compNum(compNum),
890 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
892 void start(const Node& node) {
893 _predMap.set(node, INVALID);
896 void reach(const Node& node) {
897 _numMap.set(node, _num);
898 _retMap.set(node, _num);
899 _nodeStack.push(node);
903 void leave(const Node& node) {
904 if (_numMap[node] <= _retMap[node]) {
905 while (_nodeStack.top() != node) {
906 _compMap.set(_nodeStack.top(), _compNum);
909 _compMap.set(node, _compNum);
915 void discover(const Edge& edge) {
916 _predMap.set(_graph.target(edge), edge);
919 void examine(const Edge& edge) {
920 if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
923 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
924 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
928 void backtrack(const Edge& edge) {
929 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
930 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
939 typename Graph::template NodeMap<int> _numMap;
940 typename Graph::template NodeMap<int> _retMap;
941 typename Graph::template NodeMap<Edge> _predMap;
942 std::stack<Node> _nodeStack;
947 template <typename Graph, typename EdgeMap>
948 class EdgeBiconnectedCutEdgesVisitor : public DfsVisitor<Graph> {
950 typedef typename Graph::Node Node;
951 typedef typename Graph::Edge Edge;
952 typedef typename Graph::UndirEdge UndirEdge;
954 EdgeBiconnectedCutEdgesVisitor(const Graph& graph,
955 EdgeMap& cutMap, int &cutNum)
956 : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
957 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
959 void start(const Node& node) {
960 _predMap[node] = INVALID;
963 void reach(const Node& node) {
964 _numMap.set(node, _num);
965 _retMap.set(node, _num);
969 void leave(const Node& node) {
970 if (_numMap[node] <= _retMap[node]) {
971 if (_predMap[node] != INVALID) {
972 _cutMap.set(_predMap[node], true);
978 void discover(const Edge& edge) {
979 _predMap.set(_graph.target(edge), edge);
982 void examine(const Edge& edge) {
983 if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
986 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
987 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
991 void backtrack(const Edge& edge) {
992 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
993 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1002 typename Graph::template NodeMap<int> _numMap;
1003 typename Graph::template NodeMap<int> _retMap;
1004 typename Graph::template NodeMap<Edge> _predMap;
1009 template <typename UndirGraph>
1010 int countEdgeBiconnectedComponents(const UndirGraph& graph);
1012 /// \ingroup topology
1014 /// \brief Checks that the graph is edge biconnected.
1016 /// This function checks that the graph is edge biconnected. The undirected
1017 /// graph is edge biconnected when any two nodes are connected with two
1018 /// edge-disjoint paths.
1020 /// \param graph The undirected graph.
1021 /// \return The number of components.
1022 /// \todo Make it faster.
1023 template <typename UndirGraph>
1024 bool edgeBiconnected(const UndirGraph& graph) {
1025 return countEdgeBiconnectedComponents(graph) == 1;
1028 /// \ingroup topology
1030 /// \brief Count the edge biconnected components.
1032 /// This function count the edge biconnected components in an undirected
1033 /// graph. The edge biconnected components are the classes of an equivalence
1034 /// relation on the nodes. Two nodes are in relationship when they are
1035 /// connected with at least two edge-disjoint paths.
1037 /// \param graph The undirected graph.
1038 /// \return The number of components.
1039 template <typename UndirGraph>
1040 int countEdgeBiconnectedComponents(const UndirGraph& graph) {
1041 checkConcept<concept::UndirGraph, UndirGraph>();
1042 typedef typename UndirGraph::NodeIt NodeIt;
1044 using namespace _topology_bits;
1046 typedef CountEdgeBiconnectedComponentsVisitor<UndirGraph> Visitor;
1049 Visitor visitor(graph, compNum);
1051 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
1054 for (NodeIt it(graph); it != INVALID; ++it) {
1055 if (!dfs.reached(it)) {
1063 /// \ingroup topology
1065 /// \brief Find the edge biconnected components.
1067 /// This function finds the edge biconnected components in an undirected
1068 /// graph. The edge biconnected components are the classes of an equivalence
1069 /// relation on the nodes. Two nodes are in relationship when they are
1070 /// connected at least two edge-disjoint paths.
1072 /// \param graph The graph.
1073 /// \retval comp A writable node map. The values will be set from 0 to
1074 /// the number of the biconnected components minus one. Each values
1075 /// of the map will be set exactly once, the values of a certain component
1076 /// will be set continuously.
1077 /// \return The number of components.
1078 template <typename UndirGraph, typename NodeMap>
1079 int edgeBiconnectedComponents(const UndirGraph& graph, NodeMap& compMap) {
1080 checkConcept<concept::UndirGraph, UndirGraph>();
1081 typedef typename UndirGraph::NodeIt NodeIt;
1082 typedef typename UndirGraph::Node Node;
1083 checkConcept<concept::WriteMap<Node, int>, NodeMap>();
1085 using namespace _topology_bits;
1087 typedef EdgeBiconnectedComponentsVisitor<UndirGraph, NodeMap> Visitor;
1090 Visitor visitor(graph, compMap, compNum);
1092 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
1095 for (NodeIt it(graph); it != INVALID; ++it) {
1096 if (!dfs.reached(it)) {
1104 /// \ingroup topology
1106 /// \brief Find the edge biconnected cut edges.
1108 /// This function finds the edge biconnected components in an undirected
1109 /// graph. The edge biconnected components are the classes of an equivalence
1110 /// relation on the nodes. Two nodes are in relationship when they are
1111 /// connected with at least two edge-disjoint paths. The edge biconnected
1112 /// components are separted by edges which are the cut edges of the
1115 /// \param graph The graph.
1116 /// \retval comp A writable node map. The values will be set true when the
1117 /// edge is a cut edge.
1118 /// \return The number of cut edges.
1119 template <typename UndirGraph, typename UndirEdgeMap>
1120 int edgeBiconnectedCutEdges(const UndirGraph& graph, UndirEdgeMap& cutMap) {
1121 checkConcept<concept::UndirGraph, UndirGraph>();
1122 typedef typename UndirGraph::NodeIt NodeIt;
1123 typedef typename UndirGraph::UndirEdge UndirEdge;
1124 checkConcept<concept::WriteMap<UndirEdge, bool>, UndirEdgeMap>();
1126 using namespace _topology_bits;
1128 typedef EdgeBiconnectedCutEdgesVisitor<UndirGraph, UndirEdgeMap> Visitor;
1131 Visitor visitor(graph, cutMap, cutNum);
1133 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
1136 for (NodeIt it(graph); it != INVALID; ++it) {
1137 if (!dfs.reached(it)) {
1146 namespace _topology_bits {
1148 template <typename Graph, typename IntNodeMap>
1149 class TopologicalSortVisitor : public DfsVisitor<Graph> {
1151 typedef typename Graph::Node Node;
1152 typedef typename Graph::Edge edge;
1154 TopologicalSortVisitor(IntNodeMap& order, int num)
1155 : _order(order), _num(num) {}
1157 void leave(const Node& node) {
1158 _order.set(node, --_num);
1168 /// \ingroup topology
1170 /// \brief Sort the nodes of a DAG into topolgical order.
1172 /// Sort the nodes of a DAG into topolgical order.
1174 /// \param g The graph. In must be directed and acyclic.
1175 /// \retval comp A writable node map. The values will be set from 0 to
1176 /// the number of the nodes in the graph minus one. Each values of the map
1177 /// will be set exactly once, the values will be set descending order.
1179 /// \see checkedTopologicalSort
1181 template <typename Graph, typename NodeMap>
1182 void topologicalSort(const Graph& graph, NodeMap& order) {
1183 using namespace _topology_bits;
1185 checkConcept<concept::StaticGraph, Graph>();
1186 checkConcept<concept::WriteMap<typename Graph::Node, int>, NodeMap>();
1188 typedef typename Graph::Node Node;
1189 typedef typename Graph::NodeIt NodeIt;
1190 typedef typename Graph::Edge Edge;
1192 TopologicalSortVisitor<Graph, NodeMap>
1193 visitor(order, countNodes(graph));
1195 DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
1196 dfs(graph, visitor);
1199 for (NodeIt it(graph); it != INVALID; ++it) {
1200 if (!dfs.reached(it)) {
1207 /// \ingroup topology
1209 /// \brief Sort the nodes of a DAG into topolgical order.
1211 /// Sort the nodes of a DAG into topolgical order. It also checks
1212 /// that the given graph is DAG.
1214 /// \param g The graph. In must be directed and acyclic.
1215 /// \retval order A readable - writable node map. The values will be set
1216 /// from 0 to the number of the nodes in the graph minus one. Each values
1217 /// of the map will be set exactly once, the values will be set descending
1219 /// \return %False when the graph is not DAG.
1221 /// \see topologicalSort
1223 template <typename Graph, typename NodeMap>
1224 bool checkedTopologicalSort(const Graph& graph, NodeMap& order) {
1225 using namespace _topology_bits;
1227 checkConcept<concept::StaticGraph, Graph>();
1228 checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
1230 typedef typename Graph::Node Node;
1231 typedef typename Graph::NodeIt NodeIt;
1232 typedef typename Graph::Edge Edge;
1234 order = constMap<Node, int, -1>();
1236 TopologicalSortVisitor<Graph, NodeMap>
1237 visitor(order, countNodes(graph));
1239 DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
1240 dfs(graph, visitor);
1243 for (NodeIt it(graph); it != INVALID; ++it) {
1244 if (!dfs.reached(it)) {
1246 while (!dfs.emptyQueue()) {
1247 Edge edge = dfs.nextEdge();
1248 Node target = graph.target(edge);
1249 if (dfs.reached(target) && order[target] == -1) {
1252 dfs.processNextEdge();
1259 /// \ingroup topology
1261 /// \brief Check that the given directed graph is a DAG.
1263 /// Check that the given directed graph is a DAG. The DAG is
1264 /// an Directed Acyclic Graph.
1265 /// \return %False when the graph is not DAG.
1267 template <typename Graph>
1268 bool dag(const Graph& graph) {
1270 checkConcept<concept::StaticGraph, Graph>();
1272 typedef typename Graph::Node Node;
1273 typedef typename Graph::NodeIt NodeIt;
1274 typedef typename Graph::Edge Edge;
1276 typedef typename Graph::template NodeMap<bool> ProcessedMap;
1278 typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
1281 ProcessedMap processed(graph);
1282 dfs.processedMap(processed);
1285 for (NodeIt it(graph); it != INVALID; ++it) {
1286 if (!dfs.reached(it)) {
1288 while (!dfs.emptyQueue()) {
1289 Edge edge = dfs.nextEdge();
1290 Node target = graph.target(edge);
1291 if (dfs.reached(target) && !processed[target]) {
1294 dfs.processNextEdge();
1301 /// \ingroup topology
1303 /// \brief Check that the given undirected graph is acyclic.
1305 /// Check that the given undirected graph acyclic.
1306 /// \param graph The undirected graph.
1307 /// \return %True when there is no circle in the graph.
1309 template <typename UndirGraph>
1310 bool acyclic(const UndirGraph& graph) {
1311 checkConcept<concept::UndirGraph, UndirGraph>();
1312 typedef typename UndirGraph::Node Node;
1313 typedef typename UndirGraph::NodeIt NodeIt;
1314 typedef typename UndirGraph::Edge Edge;
1315 Dfs<UndirGraph> dfs(graph);
1317 for (NodeIt it(graph); it != INVALID; ++it) {
1318 if (!dfs.reached(it)) {
1320 while (!dfs.emptyQueue()) {
1321 Edge edge = dfs.nextEdge();
1322 Node source = graph.source(edge);
1323 Node target = graph.target(edge);
1324 if (dfs.reached(target) &&
1325 dfs.pred(source) != graph.oppositeEdge(edge)) {
1328 dfs.processNextEdge();
1335 /// \ingroup topology
1337 /// \brief Check that the given undirected graph is tree.
1339 /// Check that the given undirected graph is tree.
1340 /// \param graph The undirected graph.
1341 /// \return %True when the graph is acyclic and connected.
1342 template <typename UndirGraph>
1343 bool tree(const UndirGraph& graph) {
1344 checkConcept<concept::UndirGraph, UndirGraph>();
1345 typedef typename UndirGraph::Node Node;
1346 typedef typename UndirGraph::NodeIt NodeIt;
1347 typedef typename UndirGraph::Edge Edge;
1348 Dfs<UndirGraph> dfs(graph);
1350 dfs.addSource(NodeIt(graph));
1351 while (!dfs.emptyQueue()) {
1352 Edge edge = dfs.nextEdge();
1353 Node source = graph.source(edge);
1354 Node target = graph.target(edge);
1355 if (dfs.reached(target) &&
1356 dfs.pred(source) != graph.oppositeEdge(edge)) {
1359 dfs.processNextEdge();
1361 for (NodeIt it(graph); it != INVALID; ++it) {
1362 if (!dfs.reached(it)) {
1369 /// \ingroup topology
1371 /// \brief Check that the given undirected graph is bipartite.
1373 /// Check that the given undirected graph is bipartite.
1374 /// \param graph The undirected graph.
1375 /// \return %True when the nodes can be separated into two sets that
1376 /// there are not connected nodes in neither sets.
1377 template <typename UndirGraph>
1378 bool bipartite(const UndirGraph& graph) {
1379 checkConcept<concept::UndirGraph, UndirGraph>();
1380 typedef typename UndirGraph::Node Node;
1381 typedef typename UndirGraph::NodeIt NodeIt;
1382 typedef typename UndirGraph::Edge Edge;
1383 if (NodeIt(graph) == INVALID) return false;
1384 Dfs<UndirGraph> dfs(graph);
1386 typename UndirGraph::template NodeMap<bool> red(graph);
1387 for (NodeIt it(graph); it != INVALID; ++it) {
1388 if (!dfs.reached(it)) {
1391 while (!dfs.emptyQueue()) {
1392 Edge edge = dfs.nextEdge();
1393 Node source = graph.source(edge);
1394 Node target = graph.target(edge);
1395 if (dfs.reached(target) && red[source] == red[target]) {
1398 red[target] = !red[source];
1400 dfs.processNextEdge();
1409 #endif //LEMON_TOPOLOGY_H