-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathDirectedCycleX.h
111 lines (98 loc) · 3.44 KB
/
DirectedCycleX.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#ifndef CH4_DIRECTEDCYCLEX_H
#define CH4_DIRECTEDCYCLEX_H
#include "../head/Digraph.h"
#include <queue>
using std::queue;
/**
* The {@code DirectedCycleX} class represents a data type for
* determining whether a digraph has a directed cycle.
* The <em>hasCycle</em> operation determines whether the digraph has
* a simple directed cycle and, if so, the <em>cycle</em> operation
* returns one.
* <p>
* This implementation uses a nonrecursive, queue-based algorithm.
* The constructor takes time proportional to <em>V</em> + <em>E</em>
* (in the worst case),
* where <em>V</em> is the number of vertices and <em>E</em> is the number of edges.
* Afterwards, the <em>hasCycle</em> operation takes constant time;
* the <em>cycle</em> operation takes time proportional
* to the length of the cycle.
* <p>
* See {@link DirectedCycle} for a recursive version that uses depth-first search.
* See {@link Topological} or {@link TopologicalX} to compute a topological order
* when the digraph is acyclic.
* <p>
* For additional documentation,
* see <a href="https://algs4.cs.princeton.edu/42digraph">Section 4.2</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
class DirectedCycleX {
public:
DirectedCycleX(Digraph &G) {
// indegrees of remaining vertices
vector<int> indegree(G.getV());
for (int v = 0; v < G.getV(); v++) {
indegree[v] = G.getindegree(v);
}
// initialize queue to contain all vertices with indegree = 0
queue<int> queue1;
for (int v = 0; v < G.getV(); v++)
if (indegree[v] == 0) queue1.push(v);
while (!queue1.empty()) {
int v = queue1.front();
queue1.pop();
for (int w : G.getadj(v)) {
indegree[w]--;
if (indegree[w] == 0) queue1.push(w);
}
}
// there is a directed cycle in subgraph of vertices with indegree >= 1.
vector<int> edgeTo(G.getV());
int root = -1; // any vertex with indegree >= -1
for (int v = 0; v < G.getV(); v++) {
if (indegree[v] == 0) continue;
else root = v;
for (int w : G.getadj(v)) {
if (indegree[w] > 0) {
edgeTo[w] = v;
}
}
}
if (root != -1) {
// find any vertex on cycle
vector<bool> visited(G.getV(), false);
while (!visited[root]) {
visited[root] = true;
root = edgeTo[root];
}
// extract cycle
int v = root;
do {
cycle.push_front(v);
v = edgeTo[v];
} while (v != root);
cycle.push_front(root);
}
}
/**
* Returns a directed cycle if the digraph has a directed cycle, and {@code null} otherwise.
* @return a directed cycle (as an iterable) if the digraph has a directed cycle,
* and {@code null} otherwise
*/
forward_list<int> getcycle() {
return cycle;
}
/**
* Does the digraph have a directed cycle?
* @return {@code true} if the digraph has a directed cycle, {@code false} otherwise
*/
bool hasCycle() {
return !cycle.empty();
}
private:
forward_list<int> cycle; // the directed cycle; null if digraph is acyclic
};
#endif //CH4_DIRECTEDCYCLEX_H