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 /// \image html connected_components.png
114 /// \image latex connected_components.eps "Connected components" width=\textwidth
116 /// \param g The graph. In must be undirected.
117 /// \retval comp A writable node map. The values will be set from 0 to
118 /// the number of the connected components minus one. Each values of the map
119 /// will be set exactly once, the values of a certain component will be
120 /// set continuously.
121 /// \return The number of components
123 template <class UndirGraph, class NodeMap>
124 int connectedComponents(const UndirGraph &graph, NodeMap &compMap) {
125 checkConcept<concept::UndirGraph, UndirGraph>();
126 typedef typename UndirGraph::Node Node;
127 typedef typename UndirGraph::Edge Edge;
128 checkConcept<concept::WriteMap<Node, int>, NodeMap>();
130 typedef NullMap<Node, Edge> PredMap;
131 typedef NullMap<Node, int> DistMap;
134 typename Bfs<UndirGraph>::
135 template DefPredMap<PredMap>::
136 template DefDistMap<DistMap>::
140 bfs.predMap(predMap);
143 bfs.distMap(distMap);
146 for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
147 if(!bfs.reached(n)) {
149 while (!bfs.emptyQueue()) {
150 compMap.set(bfs.nextNode(), compNum);
151 bfs.processNextNode();
159 namespace _topology_bits {
161 template <typename Graph, typename Iterator >
162 struct LeaveOrderVisitor : public DfsVisitor<Graph> {
164 typedef typename Graph::Node Node;
165 LeaveOrderVisitor(Iterator it) : _it(it) {}
167 void leave(const Node& node) {
175 template <typename Graph, typename Map>
176 struct FillMapVisitor : public DfsVisitor<Graph> {
178 typedef typename Graph::Node Node;
179 typedef typename Map::Value Value;
181 FillMapVisitor(Map& map, Value& value)
182 : _map(map), _value(value) {}
184 void reach(const Node& node) {
185 _map.set(node, _value);
192 template <typename Graph, typename EdgeMap>
193 struct StronglyConnectedCutEdgesVisitor : public DfsVisitor<Graph> {
195 typedef typename Graph::Node Node;
196 typedef typename Graph::Edge Edge;
198 StronglyConnectedCutEdgesVisitor(const Graph& graph, EdgeMap& cutMap,
200 : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
201 _compMap(graph), _num(0) {
204 void stop(const Node&) {
208 void reach(const Node& node) {
209 _compMap.set(node, _num);
212 void examine(const Edge& edge) {
213 if (_compMap[_graph.source(edge)] != _compMap[_graph.target(edge)]) {
214 _cutMap.set(edge, true);
223 typename Graph::template NodeMap<int> _compMap;
230 /// \ingroup topology
232 /// \brief Check that the given directed graph is strongly connected.
234 /// Check that the given directed graph is strongly connected. The
235 /// graph is strongly connected when any two nodes of the graph are
236 /// connected with directed pathes in both direction.
237 /// \return %False when the graph is not strongly connected.
240 /// \waning Empty graph is not strongly connected.
241 template <typename Graph>
242 bool stronglyConnected(const Graph& graph) {
243 checkConcept<concept::StaticGraph, Graph>();
244 if (NodeIt(graph) == INVALID) return false;
246 typedef typename Graph::Node Node;
247 typedef typename Graph::NodeIt NodeIt;
249 using namespace _topology_bits;
251 typedef DfsVisitor<Graph> Visitor;
254 DfsVisit<Graph, Visitor> dfs(graph, visitor);
256 dfs.addSource(NodeIt(graph));
259 for (NodeIt it(graph); it != INVALID; ++it) {
260 if (!dfs.reached(it)) {
265 typedef RevGraphAdaptor<const Graph> RGraph;
266 RGraph rgraph(graph);
268 typedef DfsVisitor<Graph> RVisitor;
271 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
273 rdfs.addSource(NodeIt(graph));
276 for (NodeIt it(graph); it != INVALID; ++it) {
277 if (!rdfs.reached(it)) {
285 /// \ingroup topology
287 /// \brief Count the strongly connected components of a directed graph
289 /// Count the strongly connected components of a directed graph.
290 /// The strongly connected components are the classes of an equivalence
291 /// relation on the nodes of the graph. Two nodes are connected with
292 /// directed paths in both direction.
294 /// \param g The graph.
295 /// \return The number of components
296 template <typename Graph>
297 int countStronglyConnectedComponents(const Graph& graph) {
298 checkConcept<concept::StaticGraph, Graph>();
300 using namespace _topology_bits;
302 typedef typename Graph::Node Node;
303 typedef typename Graph::Edge Edge;
304 typedef typename Graph::NodeIt NodeIt;
305 typedef typename Graph::EdgeIt EdgeIt;
307 typedef std::vector<Node> Container;
308 typedef typename Container::iterator Iterator;
310 Container nodes(countNodes(graph));
311 typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
312 Visitor visitor(nodes.begin());
314 DfsVisit<Graph, Visitor> dfs(graph, visitor);
316 for (NodeIt it(graph); it != INVALID; ++it) {
317 if (!dfs.reached(it)) {
323 typedef typename Container::reverse_iterator RIterator;
324 typedef RevGraphAdaptor<const Graph> RGraph;
326 RGraph rgraph(graph);
328 typedef DfsVisitor<Graph> RVisitor;
331 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
336 for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
337 if (!rdfs.reached(*it)) {
346 /// \ingroup topology
348 /// \brief Find the strongly connected components of a directed graph
350 /// Find the strongly connected components of a directed graph.
351 /// The strongly connected components are the classes of an equivalence
352 /// relation on the nodes of the graph. Two nodes are in relationship
353 /// when there are directed paths between them in both direction.
355 /// \image html strongly_connected_components.png
356 /// \image latex strongly_connected_components.eps "Strongly connected components" width=\textwidth
358 /// \param g The graph.
359 /// \retval comp A writable node map. The values will be set from 0 to
360 /// the number of the strongly connected components minus one. Each values
361 /// of the map will be set exactly once, the values of a certain component
362 /// will be set continuously.
363 /// \return The number of components
365 template <typename Graph, typename NodeMap>
366 int stronglyConnectedComponents(const Graph& graph, NodeMap& compMap) {
367 checkConcept<concept::StaticGraph, Graph>();
368 typedef typename Graph::Node Node;
369 typedef typename Graph::NodeIt NodeIt;
370 checkConcept<concept::WriteMap<Node, int>, NodeMap>();
372 using namespace _topology_bits;
374 typedef std::vector<Node> Container;
375 typedef typename Container::iterator Iterator;
377 Container nodes(countNodes(graph));
378 typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
379 Visitor visitor(nodes.begin());
381 DfsVisit<Graph, Visitor> dfs(graph, visitor);
383 for (NodeIt it(graph); it != INVALID; ++it) {
384 if (!dfs.reached(it)) {
390 typedef typename Container::reverse_iterator RIterator;
391 typedef RevGraphAdaptor<const Graph> RGraph;
393 RGraph rgraph(graph);
397 typedef FillMapVisitor<RGraph, NodeMap> RVisitor;
398 RVisitor rvisitor(compMap, compNum);
400 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
403 for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
404 if (!rdfs.reached(*it)) {
413 /// \ingroup topology
415 /// \brief Find the cut edges of the strongly connected components.
417 /// Find the cut edges of the strongly connected components.
418 /// The strongly connected components are the classes of an equivalence
419 /// relation on the nodes of the graph. Two nodes are in relationship
420 /// when there are directed paths between them in both direction.
421 /// The strongly connected components are separated by the cut edges.
423 /// \param g The graph.
424 /// \retval comp A writable edge map. The values will be set true when
425 /// the edge is cut edge otherwise false.
427 /// \return The number of cut edges
428 template <typename Graph, typename EdgeMap>
429 int stronglyConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
430 checkConcept<concept::StaticGraph, Graph>();
431 typedef typename Graph::Node Node;
432 typedef typename Graph::Edge Edge;
433 typedef typename Graph::NodeIt NodeIt;
434 checkConcept<concept::WriteMap<Edge, bool>, EdgeMap>();
436 using namespace _topology_bits;
438 typedef std::vector<Node> Container;
439 typedef typename Container::iterator Iterator;
441 Container nodes(countNodes(graph));
442 typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
443 Visitor visitor(nodes.begin());
445 DfsVisit<Graph, Visitor> dfs(graph, visitor);
447 for (NodeIt it(graph); it != INVALID; ++it) {
448 if (!dfs.reached(it)) {
454 typedef typename Container::reverse_iterator RIterator;
455 typedef RevGraphAdaptor<const Graph> RGraph;
457 RGraph rgraph(graph);
461 typedef StronglyConnectedCutEdgesVisitor<RGraph, EdgeMap> RVisitor;
462 RVisitor rvisitor(rgraph, cutMap, cutNum);
464 DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
467 for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
468 if (!rdfs.reached(*it)) {
476 namespace _topology_bits {
478 template <typename Graph>
479 class CountNodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
481 typedef typename Graph::Node Node;
482 typedef typename Graph::Edge Edge;
483 typedef typename Graph::UndirEdge UndirEdge;
485 CountNodeBiconnectedComponentsVisitor(const Graph& graph, int &compNum)
486 : _graph(graph), _compNum(compNum),
487 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
489 void start(const Node& node) {
490 _predMap.set(node, INVALID);
493 void reach(const Node& node) {
494 _numMap.set(node, _num);
495 _retMap.set(node, _num);
499 void discover(const Edge& edge) {
500 _predMap.set(_graph.target(edge), _graph.source(edge));
503 void examine(const Edge& edge) {
504 if (_graph.source(edge) == _graph.target(edge) &&
505 _graph.direction(edge)) {
509 if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
512 if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
513 _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
517 void backtrack(const Edge& edge) {
518 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
519 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
521 if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
530 typename Graph::template NodeMap<int> _numMap;
531 typename Graph::template NodeMap<int> _retMap;
532 typename Graph::template NodeMap<Node> _predMap;
536 template <typename Graph, typename EdgeMap>
537 class NodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
539 typedef typename Graph::Node Node;
540 typedef typename Graph::Edge Edge;
541 typedef typename Graph::UndirEdge UndirEdge;
543 NodeBiconnectedComponentsVisitor(const Graph& graph,
544 EdgeMap& compMap, int &compNum)
545 : _graph(graph), _compMap(compMap), _compNum(compNum),
546 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
548 void start(const Node& node) {
549 _predMap.set(node, INVALID);
552 void reach(const Node& node) {
553 _numMap.set(node, _num);
554 _retMap.set(node, _num);
558 void discover(const Edge& edge) {
559 Node target = _graph.target(edge);
560 _predMap.set(target, edge);
561 _edgeStack.push(edge);
564 void examine(const Edge& edge) {
565 Node source = _graph.source(edge);
566 Node target = _graph.target(edge);
567 if (source == target && _graph.direction(edge)) {
568 _compMap.set(edge, _compNum);
572 if (_numMap[target] < _numMap[source]) {
573 if (_predMap[source] != _graph.oppositeEdge(edge)) {
574 _edgeStack.push(edge);
577 if (_predMap[source] != INVALID &&
578 target == _graph.source(_predMap[source])) {
581 if (_retMap[source] > _numMap[target]) {
582 _retMap.set(source, _numMap[target]);
586 void backtrack(const Edge& edge) {
587 Node source = _graph.source(edge);
588 Node target = _graph.target(edge);
589 if (_retMap[source] > _retMap[target]) {
590 _retMap.set(source, _retMap[target]);
592 if (_numMap[source] <= _retMap[target]) {
593 while (_edgeStack.top() != edge) {
594 _compMap.set(_edgeStack.top(), _compNum);
597 _compMap.set(edge, _compNum);
608 typename Graph::template NodeMap<int> _numMap;
609 typename Graph::template NodeMap<int> _retMap;
610 typename Graph::template NodeMap<Edge> _predMap;
611 std::stack<UndirEdge> _edgeStack;
616 template <typename Graph, typename NodeMap>
617 class NodeBiconnectedCutNodesVisitor : public DfsVisitor<Graph> {
619 typedef typename Graph::Node Node;
620 typedef typename Graph::Edge Edge;
621 typedef typename Graph::UndirEdge UndirEdge;
623 NodeBiconnectedCutNodesVisitor(const Graph& graph, NodeMap& cutMap,
625 : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
626 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
628 void start(const Node& node) {
629 _predMap.set(node, INVALID);
633 void reach(const Node& node) {
634 _numMap.set(node, _num);
635 _retMap.set(node, _num);
639 void discover(const Edge& edge) {
640 _predMap.set(_graph.target(edge), _graph.source(edge));
643 void examine(const Edge& edge) {
644 if (_graph.source(edge) == _graph.target(edge) &&
645 _graph.direction(edge)) {
646 if (!_cutMap[_graph.source(edge)]) {
647 _cutMap.set(_graph.source(edge), true);
652 if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
653 if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
654 _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
658 void backtrack(const Edge& edge) {
659 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
660 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
662 if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
663 if (_predMap[_graph.source(edge)] != INVALID) {
664 if (!_cutMap[_graph.source(edge)]) {
665 _cutMap.set(_graph.source(edge), true);
668 } else if (rootCut) {
669 if (!_cutMap[_graph.source(edge)]) {
670 _cutMap.set(_graph.source(edge), true);
684 typename Graph::template NodeMap<int> _numMap;
685 typename Graph::template NodeMap<int> _retMap;
686 typename Graph::template NodeMap<Node> _predMap;
687 std::stack<UndirEdge> _edgeStack;
694 template <typename UndirGraph>
695 int countNodeBiconnectedComponents(const UndirGraph& graph);
697 /// \ingroup topology
699 /// \brief Checks the graph is bi-node-connected.
701 /// This function checks that the undirected graph is bi-node-connected
702 /// graph. The graph is bi-node-connected if any two undirected edge is
705 /// \param graph The graph.
706 /// \return %True when the graph bi-node-connected.
707 /// \todo Make it faster.
708 template <typename UndirGraph>
709 bool biNodeConnected(const UndirGraph& graph) {
710 return countNodeBiconnectedComponents(graph) == 1;
713 /// \ingroup topology
715 /// \brief Count the biconnected components.
717 /// This function finds the bi-node-connected components in an undirected
718 /// graph. The biconnected components are the classes of an equivalence
719 /// relation on the undirected edges. Two undirected edge is in relationship
720 /// when they are on same circle.
722 /// \param graph The graph.
723 /// \return The number of components.
724 template <typename UndirGraph>
725 int countNodeBiconnectedComponents(const UndirGraph& graph) {
726 checkConcept<concept::UndirGraph, UndirGraph>();
727 typedef typename UndirGraph::NodeIt NodeIt;
729 using namespace _topology_bits;
731 typedef CountNodeBiconnectedComponentsVisitor<UndirGraph> Visitor;
734 Visitor visitor(graph, compNum);
736 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
739 for (NodeIt it(graph); it != INVALID; ++it) {
740 if (!dfs.reached(it)) {
748 /// \ingroup topology
750 /// \brief Find the bi-node-connected components.
752 /// This function finds the bi-node-connected components in an undirected
753 /// graph. The bi-node-connected components are the classes of an equivalence
754 /// relation on the undirected edges. Two undirected edge are in relationship
755 /// when they are on same circle.
757 /// \image html node_biconnected_components.png
758 /// \image latex node_biconnected_components.eps "bi-node-connected components" width=\textwidth
760 /// \param graph The graph.
761 /// \retval comp A writable undir edge map. The values will be set from 0 to
762 /// the number of the biconnected components minus one. Each values
763 /// of the map will be set exactly once, the values of a certain component
764 /// will be set continuously.
765 /// \return The number of components.
767 template <typename UndirGraph, typename UndirEdgeMap>
768 int biNodeConnectedComponents(const UndirGraph& graph,
769 UndirEdgeMap& compMap) {
770 checkConcept<concept::UndirGraph, UndirGraph>();
771 typedef typename UndirGraph::NodeIt NodeIt;
772 typedef typename UndirGraph::UndirEdge UndirEdge;
773 checkConcept<concept::WriteMap<UndirEdge, int>, UndirEdgeMap>();
775 using namespace _topology_bits;
777 typedef NodeBiconnectedComponentsVisitor<UndirGraph, UndirEdgeMap> Visitor;
780 Visitor visitor(graph, compMap, compNum);
782 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
785 for (NodeIt it(graph); it != INVALID; ++it) {
786 if (!dfs.reached(it)) {
794 /// \ingroup topology
796 /// \brief Find the bi-node-connected cut nodes.
798 /// This function finds the bi-node-connected cut nodes in an undirected
799 /// graph. The bi-node-connected components are the classes of an equivalence
800 /// relation on the undirected edges. Two undirected edges are in
801 /// relationship when they are on same circle. The biconnected components
802 /// are separted by nodes which are the cut nodes of the components.
804 /// \param graph The graph.
805 /// \retval comp A writable edge map. The values will be set true when
806 /// the node separate two or more components.
807 /// \return The number of the cut nodes.
808 template <typename UndirGraph, typename NodeMap>
809 int biNodeConnectedCutNodes(const UndirGraph& graph, NodeMap& cutMap) {
810 checkConcept<concept::UndirGraph, UndirGraph>();
811 typedef typename UndirGraph::Node Node;
812 typedef typename UndirGraph::NodeIt NodeIt;
813 checkConcept<concept::WriteMap<Node, bool>, NodeMap>();
815 using namespace _topology_bits;
817 typedef NodeBiconnectedCutNodesVisitor<UndirGraph, NodeMap> Visitor;
820 Visitor visitor(graph, cutMap, cutNum);
822 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
825 for (NodeIt it(graph); it != INVALID; ++it) {
826 if (!dfs.reached(it)) {
834 namespace _topology_bits {
836 template <typename Graph>
837 class CountEdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
839 typedef typename Graph::Node Node;
840 typedef typename Graph::Edge Edge;
841 typedef typename Graph::UndirEdge UndirEdge;
843 CountEdgeBiconnectedComponentsVisitor(const Graph& graph, int &compNum)
844 : _graph(graph), _compNum(compNum),
845 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
847 void start(const Node& node) {
848 _predMap.set(node, INVALID);
851 void reach(const Node& node) {
852 _numMap.set(node, _num);
853 _retMap.set(node, _num);
857 void leave(const Node& node) {
858 if (_numMap[node] <= _retMap[node]) {
863 void discover(const Edge& edge) {
864 _predMap.set(_graph.target(edge), edge);
867 void examine(const Edge& edge) {
868 if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
871 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
872 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
876 void backtrack(const Edge& edge) {
877 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
878 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
886 typename Graph::template NodeMap<int> _numMap;
887 typename Graph::template NodeMap<int> _retMap;
888 typename Graph::template NodeMap<Edge> _predMap;
892 template <typename Graph, typename NodeMap>
893 class EdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
895 typedef typename Graph::Node Node;
896 typedef typename Graph::Edge Edge;
897 typedef typename Graph::UndirEdge UndirEdge;
899 EdgeBiconnectedComponentsVisitor(const Graph& graph,
900 NodeMap& compMap, int &compNum)
901 : _graph(graph), _compMap(compMap), _compNum(compNum),
902 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
904 void start(const Node& node) {
905 _predMap.set(node, INVALID);
908 void reach(const Node& node) {
909 _numMap.set(node, _num);
910 _retMap.set(node, _num);
911 _nodeStack.push(node);
915 void leave(const Node& node) {
916 if (_numMap[node] <= _retMap[node]) {
917 while (_nodeStack.top() != node) {
918 _compMap.set(_nodeStack.top(), _compNum);
921 _compMap.set(node, _compNum);
927 void discover(const Edge& edge) {
928 _predMap.set(_graph.target(edge), edge);
931 void examine(const Edge& edge) {
932 if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
935 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
936 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
940 void backtrack(const Edge& edge) {
941 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
942 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
951 typename Graph::template NodeMap<int> _numMap;
952 typename Graph::template NodeMap<int> _retMap;
953 typename Graph::template NodeMap<Edge> _predMap;
954 std::stack<Node> _nodeStack;
959 template <typename Graph, typename EdgeMap>
960 class EdgeBiconnectedCutEdgesVisitor : public DfsVisitor<Graph> {
962 typedef typename Graph::Node Node;
963 typedef typename Graph::Edge Edge;
964 typedef typename Graph::UndirEdge UndirEdge;
966 EdgeBiconnectedCutEdgesVisitor(const Graph& graph,
967 EdgeMap& cutMap, int &cutNum)
968 : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
969 _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
971 void start(const Node& node) {
972 _predMap[node] = INVALID;
975 void reach(const Node& node) {
976 _numMap.set(node, _num);
977 _retMap.set(node, _num);
981 void leave(const Node& node) {
982 if (_numMap[node] <= _retMap[node]) {
983 if (_predMap[node] != INVALID) {
984 _cutMap.set(_predMap[node], true);
990 void discover(const Edge& edge) {
991 _predMap.set(_graph.target(edge), edge);
994 void examine(const Edge& edge) {
995 if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
998 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
999 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1003 void backtrack(const Edge& edge) {
1004 if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1005 _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1010 const Graph& _graph;
1014 typename Graph::template NodeMap<int> _numMap;
1015 typename Graph::template NodeMap<int> _retMap;
1016 typename Graph::template NodeMap<Edge> _predMap;
1021 template <typename UndirGraph>
1022 int countEdgeBiconnectedComponents(const UndirGraph& graph);
1024 /// \ingroup topology
1026 /// \brief Checks that the graph is bi-edge-connected.
1028 /// This function checks that the graph is bi-edge-connected. The undirected
1029 /// graph is bi-edge-connected when any two nodes are connected with two
1030 /// edge-disjoint paths.
1032 /// \param graph The undirected graph.
1033 /// \return The number of components.
1034 /// \todo Make it faster.
1035 template <typename UndirGraph>
1036 bool biEdgeConnected(const UndirGraph& graph) {
1037 return countEdgeBiconnectedComponents(graph) == 1;
1040 /// \ingroup topology
1042 /// \brief Count the bi-edge-connected components.
1044 /// This function count the bi-edge-connected components in an undirected
1045 /// graph. The bi-edge-connected components are the classes of an equivalence
1046 /// relation on the nodes. Two nodes are in relationship when they are
1047 /// connected with at least two edge-disjoint paths.
1049 /// \param graph The undirected graph.
1050 /// \return The number of components.
1051 template <typename UndirGraph>
1052 int countEdgeBiconnectedComponents(const UndirGraph& graph) {
1053 checkConcept<concept::UndirGraph, UndirGraph>();
1054 typedef typename UndirGraph::NodeIt NodeIt;
1056 using namespace _topology_bits;
1058 typedef CountEdgeBiconnectedComponentsVisitor<UndirGraph> Visitor;
1061 Visitor visitor(graph, compNum);
1063 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
1066 for (NodeIt it(graph); it != INVALID; ++it) {
1067 if (!dfs.reached(it)) {
1075 /// \ingroup topology
1077 /// \brief Find the bi-edge-connected components.
1079 /// This function finds the bi-edge-connected components in an undirected
1080 /// graph. The bi-edge-connected components are the classes of an equivalence
1081 /// relation on the nodes. Two nodes are in relationship when they are
1082 /// connected at least two edge-disjoint paths.
1084 /// \image html edge_biconnected_components.png
1085 /// \image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth
1087 /// \param graph The graph.
1088 /// \retval comp A writable node map. The values will be set from 0 to
1089 /// the number of the biconnected components minus one. Each values
1090 /// of the map will be set exactly once, the values of a certain component
1091 /// will be set continuously.
1092 /// \return The number of components.
1094 template <typename UndirGraph, typename NodeMap>
1095 int biEdgeConnectedComponents(const UndirGraph& graph, NodeMap& compMap) {
1096 checkConcept<concept::UndirGraph, UndirGraph>();
1097 typedef typename UndirGraph::NodeIt NodeIt;
1098 typedef typename UndirGraph::Node Node;
1099 checkConcept<concept::WriteMap<Node, int>, NodeMap>();
1101 using namespace _topology_bits;
1103 typedef EdgeBiconnectedComponentsVisitor<UndirGraph, NodeMap> Visitor;
1106 Visitor visitor(graph, compMap, compNum);
1108 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
1111 for (NodeIt it(graph); it != INVALID; ++it) {
1112 if (!dfs.reached(it)) {
1120 /// \ingroup topology
1122 /// \brief Find the bi-edge-connected cut edges.
1124 /// This function finds the bi-edge-connected components in an undirected
1125 /// graph. The bi-edge-connected components are the classes of an equivalence
1126 /// relation on the nodes. Two nodes are in relationship when they are
1127 /// connected with at least two edge-disjoint paths. The bi-edge-connected
1128 /// components are separted by edges which are the cut edges of the
1131 /// \param graph The graph.
1132 /// \retval comp A writable node map. The values will be set true when the
1133 /// edge is a cut edge.
1134 /// \return The number of cut edges.
1135 template <typename UndirGraph, typename UndirEdgeMap>
1136 int biEdgeConnectedCutEdges(const UndirGraph& graph, UndirEdgeMap& cutMap) {
1137 checkConcept<concept::UndirGraph, UndirGraph>();
1138 typedef typename UndirGraph::NodeIt NodeIt;
1139 typedef typename UndirGraph::UndirEdge UndirEdge;
1140 checkConcept<concept::WriteMap<UndirEdge, bool>, UndirEdgeMap>();
1142 using namespace _topology_bits;
1144 typedef EdgeBiconnectedCutEdgesVisitor<UndirGraph, UndirEdgeMap> Visitor;
1147 Visitor visitor(graph, cutMap, cutNum);
1149 DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
1152 for (NodeIt it(graph); it != INVALID; ++it) {
1153 if (!dfs.reached(it)) {
1162 namespace _topology_bits {
1164 template <typename Graph, typename IntNodeMap>
1165 class TopologicalSortVisitor : public DfsVisitor<Graph> {
1167 typedef typename Graph::Node Node;
1168 typedef typename Graph::Edge edge;
1170 TopologicalSortVisitor(IntNodeMap& order, int num)
1171 : _order(order), _num(num) {}
1173 void leave(const Node& node) {
1174 _order.set(node, --_num);
1184 /// \ingroup topology
1186 /// \brief Sort the nodes of a DAG into topolgical order.
1188 /// Sort the nodes of a DAG into topolgical order.
1190 /// \param g The graph. In must be directed and acyclic.
1191 /// \retval comp A writable node map. The values will be set from 0 to
1192 /// the number of the nodes in the graph minus one. Each values of the map
1193 /// will be set exactly once, the values will be set descending order.
1195 /// \see checkedTopologicalSort
1197 template <typename Graph, typename NodeMap>
1198 void topologicalSort(const Graph& graph, NodeMap& order) {
1199 using namespace _topology_bits;
1201 checkConcept<concept::StaticGraph, Graph>();
1202 checkConcept<concept::WriteMap<typename Graph::Node, int>, NodeMap>();
1204 typedef typename Graph::Node Node;
1205 typedef typename Graph::NodeIt NodeIt;
1206 typedef typename Graph::Edge Edge;
1208 TopologicalSortVisitor<Graph, NodeMap>
1209 visitor(order, countNodes(graph));
1211 DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
1212 dfs(graph, visitor);
1215 for (NodeIt it(graph); it != INVALID; ++it) {
1216 if (!dfs.reached(it)) {
1223 /// \ingroup topology
1225 /// \brief Sort the nodes of a DAG into topolgical order.
1227 /// Sort the nodes of a DAG into topolgical order. It also checks
1228 /// that the given graph is DAG.
1230 /// \param g The graph. In must be directed and acyclic.
1231 /// \retval order A readable - writable node map. The values will be set
1232 /// from 0 to the number of the nodes in the graph minus one. Each values
1233 /// of the map will be set exactly once, the values will be set descending
1235 /// \return %False when the graph is not DAG.
1237 /// \see topologicalSort
1239 template <typename Graph, typename NodeMap>
1240 bool checkedTopologicalSort(const Graph& graph, NodeMap& order) {
1241 using namespace _topology_bits;
1243 checkConcept<concept::StaticGraph, Graph>();
1244 checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
1246 typedef typename Graph::Node Node;
1247 typedef typename Graph::NodeIt NodeIt;
1248 typedef typename Graph::Edge Edge;
1250 order = constMap<Node, int, -1>();
1252 TopologicalSortVisitor<Graph, NodeMap>
1253 visitor(order, countNodes(graph));
1255 DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
1256 dfs(graph, visitor);
1259 for (NodeIt it(graph); it != INVALID; ++it) {
1260 if (!dfs.reached(it)) {
1262 while (!dfs.emptyQueue()) {
1263 Edge edge = dfs.nextEdge();
1264 Node target = graph.target(edge);
1265 if (dfs.reached(target) && order[target] == -1) {
1268 dfs.processNextEdge();
1275 /// \ingroup topology
1277 /// \brief Check that the given directed graph is a DAG.
1279 /// Check that the given directed graph is a DAG. The DAG is
1280 /// an Directed Acyclic Graph.
1281 /// \return %False when the graph is not DAG.
1283 template <typename Graph>
1284 bool dag(const Graph& graph) {
1286 checkConcept<concept::StaticGraph, Graph>();
1288 typedef typename Graph::Node Node;
1289 typedef typename Graph::NodeIt NodeIt;
1290 typedef typename Graph::Edge Edge;
1292 typedef typename Graph::template NodeMap<bool> ProcessedMap;
1294 typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
1297 ProcessedMap processed(graph);
1298 dfs.processedMap(processed);
1301 for (NodeIt it(graph); it != INVALID; ++it) {
1302 if (!dfs.reached(it)) {
1304 while (!dfs.emptyQueue()) {
1305 Edge edge = dfs.nextEdge();
1306 Node target = graph.target(edge);
1307 if (dfs.reached(target) && !processed[target]) {
1310 dfs.processNextEdge();
1317 /// \ingroup topology
1319 /// \brief Check that the given undirected graph is acyclic.
1321 /// Check that the given undirected graph acyclic.
1322 /// \param graph The undirected graph.
1323 /// \return %True when there is no circle in the graph.
1325 template <typename UndirGraph>
1326 bool acyclic(const UndirGraph& graph) {
1327 checkConcept<concept::UndirGraph, UndirGraph>();
1328 typedef typename UndirGraph::Node Node;
1329 typedef typename UndirGraph::NodeIt NodeIt;
1330 typedef typename UndirGraph::Edge Edge;
1331 Dfs<UndirGraph> dfs(graph);
1333 for (NodeIt it(graph); it != INVALID; ++it) {
1334 if (!dfs.reached(it)) {
1336 while (!dfs.emptyQueue()) {
1337 Edge edge = dfs.nextEdge();
1338 Node source = graph.source(edge);
1339 Node target = graph.target(edge);
1340 if (dfs.reached(target) &&
1341 dfs.predEdge(source) != graph.oppositeEdge(edge)) {
1344 dfs.processNextEdge();
1351 /// \ingroup topology
1353 /// \brief Check that the given undirected graph is tree.
1355 /// Check that the given undirected graph is tree.
1356 /// \param graph The undirected graph.
1357 /// \return %True when the graph is acyclic and connected.
1358 template <typename UndirGraph>
1359 bool tree(const UndirGraph& graph) {
1360 checkConcept<concept::UndirGraph, UndirGraph>();
1361 typedef typename UndirGraph::Node Node;
1362 typedef typename UndirGraph::NodeIt NodeIt;
1363 typedef typename UndirGraph::Edge Edge;
1364 Dfs<UndirGraph> dfs(graph);
1366 dfs.addSource(NodeIt(graph));
1367 while (!dfs.emptyQueue()) {
1368 Edge edge = dfs.nextEdge();
1369 Node source = graph.source(edge);
1370 Node target = graph.target(edge);
1371 if (dfs.reached(target) &&
1372 dfs.predEdge(source) != graph.oppositeEdge(edge)) {
1375 dfs.processNextEdge();
1377 for (NodeIt it(graph); it != INVALID; ++it) {
1378 if (!dfs.reached(it)) {
1385 /// \ingroup topology
1387 /// \brief Check that the given undirected graph is bipartite.
1389 /// Check that the given undirected graph is bipartite.
1390 /// \param graph The undirected graph.
1391 /// \return %True when the nodes can be separated into two sets that
1392 /// there are not connected nodes in neither sets.
1393 template <typename UndirGraph>
1394 bool bipartite(const UndirGraph& graph) {
1395 checkConcept<concept::UndirGraph, UndirGraph>();
1396 typedef typename UndirGraph::Node Node;
1397 typedef typename UndirGraph::NodeIt NodeIt;
1398 typedef typename UndirGraph::Edge Edge;
1399 if (NodeIt(graph) == INVALID) return false;
1400 Dfs<UndirGraph> dfs(graph);
1402 typename UndirGraph::template NodeMap<bool> red(graph);
1403 for (NodeIt it(graph); it != INVALID; ++it) {
1404 if (!dfs.reached(it)) {
1407 while (!dfs.emptyQueue()) {
1408 Edge edge = dfs.nextEdge();
1409 Node source = graph.source(edge);
1410 Node target = graph.target(edge);
1411 if (dfs.reached(target) && red[source] == red[target]) {
1414 red[target] = !red[source];
1416 dfs.processNextEdge();
1425 #endif //LEMON_TOPOLOGY_H