class Vectex { public int Index;//代表该顶点的下标 public Vectex(int index) { Index = index; } } class Edge { public Vectex From,To; public int Weight; public Edge(Vectex from, Vectex to,int weight) { From = from; To = to; Weight = weight; } } class Program { static void Main(string[] args) { //构建图 Vectex O = new Vectex(0); Vectex A = new Vectex(1); Vectex B = new Vectex(2); Vectex C = new Vectex(3); Vectex D = new Vectex(4); Vectex[] vectexs = new Vectex[] { O, A, B, C, D }; Dictionary<Vectex, Edge[]> datas = new Dictionary<Vectex, Edge[]>(); Edge OA = new Edge(O, A, 2); Edge OB = new Edge(O, B, 3); Edge AC = new Edge(A, C, 7); Edge AD = new Edge(A, D, -1); Edge BD = new Edge(B, D, 1); Edge DC = new Edge(D, C, 2); datas.Add(O, new Edge[] { OA, OB }); datas.Add(A, new Edge[] { AC,AD }); datas.Add(B, new Edge[] { BD }); datas.Add(D, new Edge[] { DC }); //构建图 结束 int[] results = Ford(datas, vectexs); foreach (var ii in results) { Console.Write(ii + " "); } Console.ReadKey(); } static int[] Ford(Dictionary<Vectex,Edge[]> datas, Vectex[] vectexs) { int vNum = vectexs.Length; int[] book = new int[vNum]; int[] dis = new int[vNum]; //初始化记录从原点到目标点的最短路径长度 for (int i = 0; i < vNum; i++) { dis[i] = int.MaxValue; } dis[0] = 0; Queue<Vectex> queue = new Queue<Vectex>(); queue.Enqueue(vectexs[0]); book[0] = 1; Vectex v; while(queue.Count>0){ v = queue.Dequeue(); Edge[] edges; datas.TryGetValue(v, out edges); book[v.Index] = 0; if (edges == null) { continue; } foreach (var e in edges) { if (dis[e.To.Index] > dis[v.Index] + e.Weight) { //如果有需要,可以增加一个父节点记录数组,这样就可以通过目标点得到路径了 dis[e.To.Index] = dis[v.Index] + e.Weight; if(book[e.To.Index == 0){ queue.Enqueue(e.To); book[e.To.Index] = 1; } } } } return dis; } }
可以计算有负权值的图,这里计算了每一个点距离原点的最短距离。用一个队列来记录可能需要优化的顶点,还有一个book字典记录已经在队列中的顶点,防止同样的顶点再次进入队列,这样是没必要的。还有一个就是每个顶点距离原点的距离了。
首先初始化所有的值,队列,让原点进队。遍历队列的顶点,为每个顶点可到顶点寻找更短的路径,如果找到了,修改结果数组,把路径的结果顶点加入到队列中,因为它的值被改变了,可能会影响到它可到的顶点。当队列为空时,证明结果数组的路径都是最短路径了。
结果:0,2,3,3,1