Vous êtes sur la page 1sur 3

/* * An implementation of Bellman-Ford shortest path algorithm based on Sedgewick's implmentation where * edge weights may be negative.

* The inputs are an edge weighted directed graph and an individual vertex in the graph. The output * will be the shortest paths from the vertex to all other vertices it is connect ed to. * */ public class BellmanFordSP { /* * an array to keep track of the distance from our starting vertex to * all connected vertices * */ private double[] _distTo; /* * an array of edges in our shortest paths * it is interesting to not for all vertices in the shortest paths * there is only one edge to each vertex which is why we can use * a simple DirectedEdge array * */ private DirectedEdge[] _edgeTo; //helps us keep track of which vertices are in our shortest paths private bool[] _onQueue; //helps us keep track of which vertices are in our shortest paths private Queue<Int32> _queue; private int _cost; //If there is a negative cycle, this list will contain the edges in it private IEnumerable<DirectedEdge> _cycle; /* * The inputs are an edge weighted directed graph and * a starting vertex * */ public BellmanFordSP(EdgeWeightedDigraph G, int s) { /* * initialize our arrays and set the default values * for weights to positive infinity * */ _distTo = new double[G.V()]; _edgeTo = new DirectedEdge[G.V()]; _onQueue = new bool[G.V()]; for (int v = 0; v < G.V(); v++) _distTo[v] = Double.PositiveInfinity; _distTo[s] = 0.0; _queue = new Queue<Int32>(); _queue.Enqueue(s); _onQueue[s] = true; while (!(_queue.Count() <= 0) && !HasNegativeCycle()) { //get a vertex from the queue and remove it from the queue int v = _queue.Dequeue(); _onQueue[v] = false; Relax(G, v); } }

/* * Relax is the main method for helping us determin what * the minimum path is to a connected vertex. * */ private void Relax(EdgeWeightedDigraph G, int v) { /* * for each edge connected to the vertex v: * -get a reference to the target vertex (w) * -is the distance to w through v shorter than any other path? * -update the _distTo[] array with the new path weight * -add the new edge to the _edgeTo array * -add w to the end of _queue and mark that it is in the queue * */ 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; } } /* * each time we look at an edge increment the _cost variable * when it is equal to a multiple of the number of vertices check * for an negative cycle * */ if (_cost++ % G.V() == 0) FindNegativeCycle(); } } //Indicates whether we have a negative cycle public bool HasNegativeCycle() { return _cycle != null; } //A iterable representation of the negative cycle public IEnumerable<DirectedEdge> NegativeCycle() { return _cycle; } /* * Use the EdgeWeightedDirectedCycle data structure to see if * there is a negative cycle in our graph * */ private void FindNegativeCycle() { /* * we don't want to look at the entire graph, just the * graph we've examined so far * use the edges in the _edgeTo array to create a new * edge weighted directed graph and pass that to EdgeWeightedDirectedCycl

e * */ int V = _edgeTo.Length; EdgeWeightedDigraph spt; spt = new EdgeWeightedDigraph(V); for (int v = 0; v < V; v++) { if (_edgeTo[v] != null) spt.AddEdge(_edgeTo[v]); } EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt); //_cycle will contain our negative edges _cycle = finder.Cycle(); } //Does the graph contain a path from the source vertex to vertex v? public bool HasPathTo(int v) { return _distTo[v] < Double.PositiveInfinity; } //Return the shortest distance to any connected vertex v public double DistTo(int v) { return _distTo[v]; } /* * Get the path (the series of edges/vertices) to get from * the source vertex to a given connected vertex v as an iterable list */ public IEnumerable<DirectedEdge> PathTo(int v) { if (!HasPathTo(v)) return null; Stack<DirectedEdge> path = new Stack<DirectedEdge>(); for (DirectedEdge e = _edgeTo[v]; e != null; e = _edgeTo[e.From()]) { path.Push(e); } return path; } }

Vous aimerez peut-être aussi