public DijkstraSP(EdgeWeightedDigraph g, int s) { foreach (DirectedEdge e in g.Edges()) { if (e.Weight() < 0) { throw new ArgumentOutOfRangeException("graph edge must have nonegative weights"); } } distTo = new double[g.V]; edgeTo = new DirectedEdge[g.V]; for (int v = 0; v < g.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0; //relax vertices in order of distance from s pq = new IndexMinPQ <double>(g.V); pq.Insert(s, distTo[s]); while (!pq.IsEmpty()) { int v = pq.DelMin(); foreach (DirectedEdge e in g.Adj(v)) { relax(e); } } }
/// <summary> /// check that algorithm computes either the topological order or finds a directed cycle /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void dfs(EdgeWeightedDigraph g, int v) { onStack[v] = true; marked[v] = true; foreach (DirectedEdge e in g.Adj(v)) { int w = e.To(); //short circuit if directed cycle found if (cycle != null) { return; } else if (!marked[v]) //found new vertex { edgeTo[w] = e; dfs(g, w); } // trace back directed cycle else if (onStack[w]) { cycle = new Stack <DirectedEdge>(); DirectedEdge de = e; while (de.From() != w) { cycle.Push(de); de = edgeTo[de.From()]; } cycle.Push(de); } } onStack[v] = false; }
/// <summary> /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void dfs(EdgeWeightedDigraph g, int v) { if (marked[v]) { return; } marked[v] = true; pre[v] = preCounter++; preorder.Enqueue(v); foreach (DirectedEdge e in g.Adj(v)) { int w = e.To(); if (!marked[w]) { dfs(g, w); } } postorder.Enqueue(v); post[v] = postCounter++; }
public AcyclicSP(EdgeWeightedDigraph g, int s) { distTo = new double[g.V]; edgeTo = new DirectedEdge[g.V]; for (int v = 0; v < g.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0.0; //visit vertices in toplogical order Topological topological = new Topological(g); foreach (int v in topological.Order()) { foreach (DirectedEdge e in g.Adj(v)) { relax(e); } } }
/// <summary> /// relax vertex v and put other endpoints on queue if changed /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void relax(EdgeWeightedDigraph g, int v) { foreach (DirectedEdge e in g.Adj(v)) { int w = e.To(); if (distTo[w] > distTo[v] + e.Weight()) { distTo[w] = distTo[v] + e.Weight(); edgeTo[w] = e; if (!onQueue[w]) { queue.Enqueue(w); onQueue[w] = true; } } if (cost++ % g.V == 0) { findNegativeCycle(); } } }
/// <summary> /// check optimality conditions /// (1)for all edge e: distTo[e.to()] <= distTo[e.from()] + e.weight() /// (2) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedDigraph g, int s) { //check that edge weights are nonnegative foreach (DirectedEdge e in g.Adj(s)) { int w = e.To(); if (e.Weight() < 0) { return(false); } } //check that distTo[v] and edgeTo[v] are consistent if (System.Math.Abs(distTo[s] - 0.0) > EPSILON || edgeTo[s] != null) { return(false); } for (int v = 0; v < g.V; v++) { if (v == s) { continue; } if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity) { return(false); } } //check all edges e = v-->w statisfy distTo[w] <= distTo[v] + e.weight() for (int v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { int w = e.To(); if (distTo[v] == double.PositiveInfinity || distTo[w] == double.PositiveInfinity) { continue; } if (distTo[v] + e.Weight() < distTo[w]) { return(false); } } } //check that all edge e = v-->w on spt satisfy distTo[w] = distTo[v] + e.weight() for (int w = 0; w < g.V; w++) { if (edgeTo[w] == null) { continue; } DirectedEdge e = edgeTo[w]; int v = e.From(); if (w != e.To()) { return(false); } if (distTo[v] + e.Weight() != distTo[w]) { return(false); } } return(true); }
/// <summary> /// check optimality conditions:either /// (1) there exists a negative cycle reachable from s /// (2) for all edges e = v-->w: distTo[w] <= distTo[v] + e.weight() /// (3) for all edges e = v-->w on the SPT: distTo[w] == distTo[v] + e.weight() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedDigraph g, int s) { //has a negative cycle if (HasNegativeCycle()) { double weight = 0.0; foreach (DirectedEdge e in NegativeCycle()) { weight += e.Weight(); } if (weight >= 0) { return(false); } } else { //no negative cycle reachable from s if (distTo[s] != 0.0 || edgeTo[s] != null) { return(false); } for (int v = 0; v < g.V; v++) { if (v == s) { continue; } if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity) { return(false); } } //check that all edges e=v-->w satisfy distTo[w]<=distTo[v]+e.weight() for (int v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { int w = e.To(); if (distTo[v] + e.Weight() < distTo[w]) { return(false); } } } //check that all edges e = v-->w on spt satisfy distTo[w] == distTo[v] + e.weight() for (int w = 0; w < g.V; w++) { if (edgeTo[w] == null) { continue; } DirectedEdge e = edgeTo[w]; int v = e.From(); if (w != e.To()) { return(false); } if (distTo[v] + e.Weight() != distTo[w]) { return(false); } } } return(true); }