Beispiel #1
0
        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);
        }
Beispiel #3
0
        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);
                        }
                    }
                }
            }
        }