private DirectedEdge[,] edgeTo; // edgeTo[v,w] = last edge on shortest v->w path /// <summary>Computes a shortest paths tree from each vertex to to every /// other vertex in the edge-weighted digraph <c>G</c>. If no such shortest /// path exists for some pair of vertices, it computes a negative cycle. /// </summary> /// <param name="G">the edge-weighted digraph</param> /// public FloydWarshall(AdjMatrixEdgeWeightedDigraph G) { int V = G.V; distTo = new double[V, V]; edgeTo = new DirectedEdge[V, V]; // initialize distances to infinity for (int v = 0; v < V; v++) { for (int w = 0; w < V; w++) { distTo[v, w] = double.PositiveInfinity; } } // initialize distances using edge-weighted digraph's for (int v = 0; v < G.V; v++) { foreach (DirectedEdge e in G.Adj(v)) { distTo[e.From, e.To] = e.Weight; edgeTo[e.From, e.To] = e; } // in case of self-loops if (distTo[v, v] >= 0.0) { distTo[v, v] = 0.0; edgeTo[v, v] = null; } } // Floyd-Warshall updates for (int i = 0; i < V; i++) { // compute shortest paths using only 0, 1, ..., i as intermediate vertices for (int v = 0; v < V; v++) { if (edgeTo[v, i] == null) { continue; // optimization } for (int w = 0; w < V; w++) { if (distTo[v, w] > distTo[v, i] + distTo[i, w]) { distTo[v, w] = distTo[v, i] + distTo[i, w]; edgeTo[v, w] = edgeTo[i, w]; } } // check for negative cycle if (distTo[v, v] < 0.0) { hasNegativeCycle = true; return; } } } }
public static void MainTest(string[] args) { int V = int.Parse(args[0]); int E = int.Parse(args[1]); AdjMatrixEdgeWeightedDigraph G = new AdjMatrixEdgeWeightedDigraph(V, E); Console.WriteLine(G); }
public static void MainTest(string[] args) { AdjMatrixEdgeWeightedDigraph G; if (args.Length == 1) { G = new AdjMatrixEdgeWeightedDigraph(new TextInput(args[0])); } else { // random graph with V vertices and E edges, parallel edges allowed int V = int.Parse(args[0]); int E = int.Parse(args[1]); G = new AdjMatrixEdgeWeightedDigraph(V); for (int i = 0; i < E; i++) { int v = StdRandom.Uniform(V); int w = StdRandom.Uniform(V); double weight = Math.Round(100 * (StdRandom.Uniform() - 0.15)) / 100.0; try { if (v == w) { G.AddEdge(new DirectedEdge(v, w, Math.Abs(weight))); } else { G.AddEdge(new DirectedEdge(v, w, weight)); } } catch (Exception) { Console.Error.WriteLine("What could be wrong?"); } } } Console.WriteLine(G); // run Floyd-Warshall algorithm FloydWarshall spt = new FloydWarshall(G); // print all-pairs shortest path distances Console.Write(" "); for (int v = 0; v < G.V; v++) { Console.Write("{0,6} ", v); } Console.WriteLine(); for (int v = 0; v < G.V; v++) { Console.Write("{0,3}: ", v); for (int w = 0; w < G.V; w++) { if (spt.HasPath(v, w)) { Console.Write("{0,6:F2} ", spt.Dist(v, w)); } else { Console.Write(" Inf "); } } Console.WriteLine(); } // print negative cycle if (spt.HasNegativeCycle) { Console.WriteLine("Negative cost cycle:"); foreach (DirectedEdge e in spt.NegativeCycle()) { Console.WriteLine(e); } Console.WriteLine(); } // print all-pairs shortest paths else { for (int v = 0; v < G.V; v++) { for (int w = 0; w < G.V; w++) { if (spt.HasPath(v, w)) { Console.Write("{0} to {1} ({2,5:F2}) ", v, w, spt.Dist(v, w)); foreach (DirectedEdge e in spt.Path(v, w)) { Console.Write(e + " "); } Console.WriteLine(); } else { Console.Write("{0} to {1} no path\n", v, w); } } } } }