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/graph_utils.h>
23 #include <lemon/concept/graph.h>
24 #include <lemon/concept/undir_graph.h>
25 #include <lemon/concept_check.h>
29 /// \brief Topology related algorithms
31 /// Topology related algorithms
35 namespace _topology_bits {
37 template <typename NodeMap>
38 class BackCounterMap {
40 BackCounterMap(NodeMap& _nodeMap, int _counter)
41 : nodeMap(_nodeMap), counter(_counter) {}
43 void set(typename NodeMap::Key key, bool val) {
45 nodeMap.set(key, --counter);
51 bool operator[](typename NodeMap::Key key) const {
52 return nodeMap[key] != -1;
61 // \todo Its to special output // ReadWriteMap
62 template <typename Graph, typename NodeMap>
63 bool topological_sort(const Graph& graph, NodeMap& nodeMap) {
64 using namespace _topology_bits;
66 checkConcept<concept::StaticGraph, Graph>();
67 checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
69 typedef typename Graph::Node Node;
70 typedef typename Graph::NodeIt NodeIt;
71 typedef typename Graph::Edge Edge;
73 typedef BackCounterMap<NodeMap> ProcessedMap;
75 typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
78 ProcessedMap processed(nodeMap, countNodes(graph));
80 dfs.processedMap(processed);
82 for (NodeIt it(graph); it != INVALID; ++it) {
83 if (!dfs.reached(it)) {
85 while (!dfs.emptyQueue()) {
86 Edge edge = dfs.nextEdge();
87 Node target = graph.target(edge);
88 if (dfs.reached(target) && !processed[target]) {
91 dfs.processNextEdge();
98 /// \brief Check that the given graph is a DAG.
100 /// Check that the given graph is a DAG. The DAG is
101 /// an Directed Acyclic Graph.
102 template <typename Graph>
103 bool dag(const Graph& graph) {
105 checkConcept<concept::StaticGraph, Graph>();
107 typedef typename Graph::Node Node;
108 typedef typename Graph::NodeIt NodeIt;
109 typedef typename Graph::Edge Edge;
111 typedef typename Graph::template NodeMap<bool> ProcessedMap;
113 typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
116 ProcessedMap processed(graph);
117 dfs.processedMap(processed);
120 for (NodeIt it(graph); it != INVALID; ++it) {
121 if (!dfs.reached(it)) {
123 while (!dfs.emptyQueue()) {
124 Edge edge = dfs.nextEdge();
125 Node target = graph.target(edge);
126 if (dfs.reached(target) && !processed[target]) {
129 dfs.processNextEdge();
136 // UndirGraph algorithms
138 /// \brief Check that the given undirected graph is connected.
140 /// Check that the given undirected graph connected.
141 template <typename UndirGraph>
142 bool connected(const UndirGraph& graph) {
143 checkConcept<concept::UndirGraph, UndirGraph>();
144 typedef typename UndirGraph::NodeIt NodeIt;
145 if (NodeIt(graph) == INVALID) return false;
146 Dfs<UndirGraph> dfs(graph);
147 dfs.run(NodeIt(graph));
148 for (NodeIt it(graph); it != INVALID; ++it) {
149 if (!dfs.reached(it)) {
156 /// \brief Check that the given undirected graph is acyclic.
158 /// Check that the given undirected graph acyclic.
159 template <typename UndirGraph>
160 bool acyclic(const UndirGraph& graph) {
161 checkConcept<concept::UndirGraph, UndirGraph>();
162 typedef typename UndirGraph::Node Node;
163 typedef typename UndirGraph::NodeIt NodeIt;
164 typedef typename UndirGraph::Edge Edge;
165 Dfs<UndirGraph> dfs(graph);
167 for (NodeIt it(graph); it != INVALID; ++it) {
168 if (!dfs.reached(it)) {
170 while (!dfs.emptyQueue()) {
171 Edge edge = dfs.nextEdge();
172 Node source = graph.source(edge);
173 Node target = graph.target(edge);
174 if (dfs.reached(target) &&
175 dfs.pred(source) != graph.oppositeEdge(edge)) {
178 dfs.processNextEdge();
185 /// \brief Check that the given undirected graph is tree.
187 /// Check that the given undirected graph is tree.
188 template <typename UndirGraph>
189 bool tree(const UndirGraph& graph) {
190 checkConcept<concept::UndirGraph, UndirGraph>();
191 typedef typename UndirGraph::Node Node;
192 typedef typename UndirGraph::NodeIt NodeIt;
193 typedef typename UndirGraph::Edge Edge;
194 if (NodeIt(graph) == INVALID) return false;
195 Dfs<UndirGraph> dfs(graph);
197 dfs.addSource(NodeIt(graph));
198 while (!dfs.emptyQueue()) {
199 Edge edge = dfs.nextEdge();
200 Node source = graph.source(edge);
201 Node target = graph.target(edge);
202 if (dfs.reached(target) &&
203 dfs.pred(source) != graph.oppositeEdge(edge)) {
206 dfs.processNextEdge();
208 for (NodeIt it(graph); it != INVALID; ++it) {
209 if (!dfs.reached(it)) {
219 #endif //LEMON_TOPOLOGY_H