From c462500db716f4303d7c47b997511f57c4e2532c Mon Sep 17 00:00:00 2001 From: shellfly Date: Wed, 16 May 2018 22:11:24 +0800 Subject: [PATCH] add directed_cycle.py --- README.md | 1 + algs4/directed_cycle.py | 72 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 algs4/directed_cycle.py diff --git a/README.md b/README.md index 915e446..f8b78a3 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Try to keep the interface and variable name consistent with the original book wh * [DegreesOfSeparation](algs4/degrees_of_separation.py) * [Digraph](algs4/digraph.py) * [DirectedDFS](algs4/directed_dfs.py) + * [DirectedCycle](algs4/directed_cycle.py) * 5 STRING diff --git a/algs4/directed_cycle.py b/algs4/directed_cycle.py new file mode 100644 index 0000000..73038f3 --- /dev/null +++ b/algs4/directed_cycle.py @@ -0,0 +1,72 @@ +""" + Execution: python directed_cycle.py input.txt + Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt + https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt + + Finds a directed cycle in a digraph. + Runs in O(E + V) time. + + % python directed_cycle.py tinyDG.txt + Directed cycle: 3 5 4 3 + + % python directed_cycle.py tinyDAG.txt + No directed cycle + + """ +from algs4.stack import Stack +from algs4.digraph import Digraph + + +class DirectedCycle: + + def __init__(self, G): + self._marked = [False for _ in range(G.V)] + self.edge_to = [False for _ in range(G.V)] + self.on_stack = [False for _ in range(G.V)] + self.cycle = None + for v in range(G.V): + if not self._marked[v]: + self.dfs(G, v) + + def dfs(self, G, v): + self._marked[v] = True + self.on_stack[v] = True + + for w in G.adj[v]: + if self.has_cycle(): + return + if not self._marked[w]: + self.edge_to[w] = v + self.dfs(G, w) + elif self.on_stack[w]: + self.cycle = Stack() + x = v + while x != w: + self.cycle.push(x) + x = self.edge_to[x] + self.cycle.push(w) + self.cycle.push(v) + self.on_stack[v] = False + + def marked(self, v): + return self._marked[v] + + def has_cycle(self): + return self.cycle is not None + +if __name__ == '__main__': + import sys + f = open(sys.argv[1]) + V = int(f.readline()) + E = int(f.readline()) + g = Digraph(V) + for i in range(E): + v, w = f.readline().split() + g.add_edge(v, w) + + finder = DirectedCycle(g) + if finder.has_cycle(): + for v in finder.cycle: + print(v, end=" ") + else: + print("No directed cycle")