public void TestDigraph() { Random rand = new Random(); int v = rand.Next(10, 30); Digraph g = new Digraph(v); int e0 = rand.Next(10, 30); string strs = string.Empty; for (int i = 0; i < e0; i++) { int v1 = rand.Next(0, v); int v2 = rand.Next(0, v); string str = v1 + " - " + v2 + ","; string str1 = v2 + " - " + v1 + ","; if (v1 == v2 || strs.Contains(str) || strs.Contains(str1)) { i--; continue; } g.AddEdge(v1, v2); strs += str; } Debug.WriteLine("input e: " + strs); Debug.WriteLine(g.ToString()); Digraph g1 = new Digraph(g); Debug.WriteLine("g1: "); Debug.WriteLine(g1.ToString()); }
/// <summary> /// check that algorithm computes either the topological order or finds a directed this.Cycle /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void dfs(Digraph g, int v) { this._onStack[v] = true; this._marked[v] = true; foreach (int w in g.Adj[v]) if (this.Cycle != null) { // short circuit if directed this.Cycle found return; } else if (!this._marked[w]) { //found new vertex, so recur this._edgeTo[w] = v; this.dfs(g, w); } else if (this._onStack[w]) { // trace back directed this.Cycle this.Cycle = new Stack<int>(); for (int x = v; x != w; x = this._edgeTo[x]) this.Cycle.Push(x); this.Cycle.Push(w); this.Cycle.Push(v); } this._onStack[v] = false; }
/// <summary> /// Computes the vertices in digraph G that are to any of the source vertices sources. /// </summary> /// <param name="g"></param> /// <param name="sources"></param> public DirectedDFS(Digraph g, IEnumerable<int> sources) { this.Marked = new bool[g.V]; foreach (int v in sources) if (!this.Marked[v]) this.dfs(g, v); }
public Digraph Reverse() { Digraph r = new Digraph(V); for (int v = 0; v < V; v++) foreach (int w in this.Adj[v]) r.AddEdge(w, v); return r; }
private void dfs(Digraph g, int v) { this.Marked[v] = true; this.ID[v] = this.Count; foreach (int w in g.Adj[v]) if (!this.Marked[w]) this.dfs(g, w); }
public Topological(Digraph g) { DirectedCycle cycleFinder = new DirectedCycle(g); if (!cycleFinder.HasCycle()) { DepthFirstOrder dfs = new DepthFirstOrder(g); this.Order = dfs.ReversePost; } }
/// <summary> /// Determines whether the digraph G has a directed this.Cycle and, if so, finds such a this.Cycle /// </summary> /// <param name="g"></param> public DirectedCycle(Digraph g) { this._marked = new bool[g.V]; this._onStack = new bool[g.V]; this._edgeTo = new int[g.V]; for (int v = 0; v < g.V; v++) if (!this._marked[v] && this.Cycle == null) this.dfs(g, v); }
public DepthFirstOrder(Digraph g) { this.Pre = new Queue<int>(); this.Post = new Queue<int>(); this.ReversePost = new Stack<int>(); this._marked = new bool[g.V]; for (int v = 0; v < g.V; v++) if (!this._marked[v]) this.dfs(g, v); }
private void dfs(Digraph g, int v) { this.Pre.Enqueue(v); this._marked[v] = true; foreach (int w in g.Adj[v]) if (!this._marked[w]) this.dfs(g, w); this.Post.Enqueue(v); this.ReversePost.Push(v); }
public Digraph(Digraph g) : this(g.V) { this.E = g.E; for (int v = 0; v < g.V; v++) { Part1.Stack<int> reverse = new Part1.Stack<int>(); foreach (int w in g.Adj[v]) reverse.Push(w); foreach (int w in reverse) this.Adj[v].Add(w); } }
/// <summary> /// Computes the connected components of the directed graph G. /// </summary> /// <param name="g"></param> public KosarajuSCC(Digraph g) { this.Marked = new bool[g.V]; this.ID = new int[g.V]; DepthFirstOrder order = new DepthFirstOrder(g.Reverse()); foreach (int v in order.ReversePost) if (!this.Marked[v]) { this.dfs(g, v); this.Count++; } }
public void TestDirectedCycle() { Digraph g = new Digraph(6); g.AddEdge(0, 5); g.AddEdge(5, 4); g.AddEdge(4, 3); g.AddEdge(3, 5); g.AddEdge(0, 1); g.AddEdge(1, 2); g.AddEdge(2, 3); Debug.WriteLine(g.ToString()); DirectedCycle finder = new DirectedCycle(g); if (finder.HasCycle()) { Debug.WriteLine("Directed cycle:"); foreach (var v in finder.Cycle) Debug.Write(" => " + v); } else Debug.WriteLine("No directed cycle!"); }
public void TestKosarajuSCCHasNotCycle() { Digraph g = new Digraph(6); g.AddEdge(0, 1); g.AddEdge(1, 2); g.AddEdge(2, 3); g.AddEdge(0, 4); g.AddEdge(4, 5); Debug.WriteLine(g.ToString()); DepthFirstOrder dfs = new DepthFirstOrder(g); StringBuilder sb = new StringBuilder(); foreach (var item in dfs.ReversePost) sb.Append(item + " "); Debug.WriteLine(sb.ToString()); KosarajuSCC scc = new KosarajuSCC(g); sb.Clear(); for (int i = 0; i < scc.ID.Length; i++) sb.Append(i + " - " + scc.ID[i] + Environment.NewLine); Debug.WriteLine(sb.ToString()); }
/// <summary> /// Computes the vertices in digraph G that are reachable from the source vertex s. /// </summary> /// <param name="g"></param> /// <param name="s"></param> public DirectedDFS(Digraph g, int s) { this.Marked = new bool[g.V]; this.dfs(g, s); }
public TransitiveClosure(Digraph g) { this._all = new DirectedDFS[g.V]; for (int v = 0; v < g.V; v++) this._all[v] = new DirectedDFS(g, v); }