Bellman Ford
一、贝尔曼·福特(Bellman Ford)算法概要
贝尔曼·福特(Bellman Ford)算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法。该算法由 Richard Bellman 和 Lester Ford 分别发表于 1958 年和 1956 年,而实际上 Edward F. Moore 也在 1957 年发布了相同的算法,因此,此算法也常被称为 Bellman-Ford-Moore 算法。
Bellman-Ford 算法和 Dijkstra 算法同为解决单源最短路径的算法。对于带权有向图 G = (V, E),Dijkstra 算法要求图 G 中边的权值均为非负,而 Bellman-Ford 算法能适应一般的情况(即存在负权边的情况)。一个实现的很好的 Dijkstra 算法比 Bellman-Ford 算法的运行时间要低。
二、Bellman-Ford 算法流程
(1)创建源顶点 v 到图中所有顶点的距离的集合 distSet,为图中的所有顶点指定一个距离值,初始均为 Infinite,源顶点距离为 0;
(2)计算最短路径,执行 V - 1 次遍历;
(3)对于图中的每条边:如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d;
(4)检测图中是否有负权边形成了环,遍历图中的所有边,计算 u 至 v 的距离,如果对于 v 存在更小的距离,则说明存在环;
源程序:
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace Legalsoft.Truffer.Algorithm
{
public class GraphEdge
{
public int Source { get; set; } = 0;
public int Destination { get; set; } = 0;
public int Weight { get; set; } = 0;
public GraphEdge()
{
Source = 0;
Destination = 0;
Weight = 0;
}
public GraphEdge(int s, int d, int w)
{
Source = s;
Destination = d;
Weight = w;
}
}
public partial class Graph
{
public int Vertex_Number { get; set; } = 0;
public int Edge_Number { get; set; } = 0;
public GraphEdge[] Edges { get; set; } = null;
public Graph(int v, int e)
{
Vertex_Number = v;
Edge_Number = e;
Edges = new GraphEdge[e];
for (int i = 0; i < e; i++)
{
Edges[i] = new GraphEdge();
}
}
/// <summary>
/// 按三元数组的构造函数
/// 三元数组为: {source,destination,weight}
/// </summary>
/// <param name="array"></param>
public Graph(int[,] array)
{
List<int> vn = new List<int>();
Edge_Number = array.GetLength(0);
Edges = new GraphEdge[Edge_Number];
for (int i = 0; i < Edge_Number; i++)
{
Edges[i] = new GraphEdge(array[i, 0], array[i, 1], array[i, 2]);
if (!vn.Contains(array[i, 0])) vn.Add(array[i, 0]);
if (!vn.Contains(array[i, 1])) vn.Add(array[i, 1]);
}
Vertex_Number = vn.Count;
}
public void Bellman_Ford(int src)
{
int[] dist = new int[Vertex_Number];
for (int i = 0; i < Vertex_Number; i++)
{
dist[i] = int.MaxValue;
}
dist[src] = 0;
for (int i = 1; i < Vertex_Number; i++)
{
for (int j = 0; j < Edge_Number; j++)
{
int u = Edges[j].Source;
int v = Edges[j].Destination;
int weight = Edges[j].Weight;
if (dist[u] != int.MaxValue && (dist[u] + weight) < dist[v])
{
dist[v] = dist[u] + weight;
}
}
}
for (int j = 0; j < Edge_Number; j++)
{
int u = Edges[j].Source;
int v = Edges[j].Destination;
int weight = Edges[j].Weight;
if (dist[u] != int.MaxValue && (dist[u] + weight) < dist[v])
{
return;
}
}
}
public static string Traversal(int[] dist, int src)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Vertex Distances from Source (" + src + ") is:<br>");
for (int i = 0; i < dist.Length; i++)
{
sb.AppendLine("Distance(" + i + "): " + dist[i] + "<br>");
}
return sb.ToString();
}
}
}
————————————————————
POWER BY TRUFFER.CN