1. 程式人生 > 其它 >圖最短路徑之BellmanFord

圖最短路徑之BellmanFord

定義

貝爾曼-福特演算法,可以從給定一個圖和圖中的源頂點src,找到從src到給定圖中所有頂點的最短路徑。該圖可能包含負權重邊。相對於Dijkstra演算法的優勢是可以處理負權重邊,缺點則是複雜度高於Dijkstra 。具體演算法的詳細解析請參考https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/,以下程式碼也是參考https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/,只是根據自己的需要增加了一些東西。

package graph.bellman_ford;

import lombok.Data;

public class Graph {
private final int vertexCount;
private final int edgeCount;
private final Edge[] edge;

public Graph(int vertexCount, int edgeCount, Edge[] edge) {
this.vertexCount = vertexCount;
this.edgeCount = edgeCount;
this.edge = edge;
}

@Data
public static class Edge {
Vertex source;
Vertex destination;
int weight;
}

@Data
public static class Vertex {
int sequence;
String code;
String name;
}


public void bellmanFord(Graph graph, int src) {
int[] distance = new int[vertexCount];

for (int i = 0; i < vertexCount; ++i) {
distance[i] = Integer.MAX_VALUE;
}
distance[src] = 0;


for (int i = 1; i < vertexCount; ++i) {
for (int j = 0; j < edgeCount; ++j) {
int u = graph.edge[j].source.sequence;
int v = graph.edge[j].destination.sequence;
int weight = graph.edge[j].weight;
if (distance[u] != Integer.MAX_VALUE && distance[u] + weight < distance[v]) {
distance[v] = distance[u] + weight;
}
}
}


for (int j = 0; j < edgeCount; ++j) {
int u = graph.edge[j].source.sequence;
int v = graph.edge[j].destination.sequence;
int weight = graph.edge[j].weight;
if (distance[u] != Integer.MAX_VALUE && distance[u] + weight < distance[v]) {
return;
}
}
printArr(distance, vertexCount);
}

public void printArr(int[] distance, int vertexCount) {
for (int i = 0; i < vertexCount; ++i) {
System.out.println(i + "\t\t" + distance[i]);
}
}
}

測試

package graph.bellman_ford;

import java.util.ArrayList;
import java.util.List;

public class ShortestPathOfBellmanFord {

public static void main(String[] args) {


List<Graph.Vertex> vertexList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Graph.Vertex vertex = new Graph.Vertex();
vertex.code = "code" + i;
vertex.name = "name" + i;
vertex.sequence = i;
vertexList.add(vertex);
}
Graph.Edge[] edges = new Graph.Edge[8];
for (int i = 0; i < edges.length; i++) {
edges[i] = new Graph.Edge();
}

// edge 0 --> 1
edges[0].source = vertexList.get(0);
edges[0].destination = vertexList.get(1);
edges[0].weight = -1;


// edge 0 --> 2
edges[1].source = vertexList.get(0);
edges[1].destination = vertexList.get(2);
edges[1].weight = 4;

// edge 1 --> 2
edges[2].source = vertexList.get(1);
edges[2].destination = vertexList.get(2);
edges[2].weight = 3;

// edge 1 --> 3
edges[3].source = vertexList.get(1);
edges[3].destination = vertexList.get(3);
edges[3].weight = 2;

// edge 1 --> 4
edges[4].source = vertexList.get(1);
edges[4].destination = vertexList.get(4);
edges[4].weight = 2;

// edge 3 --> 2
edges[5].source = vertexList.get(3);
edges[5].destination = vertexList.get(2);
edges[5].weight = 5;

// edge 3 --> 1
edges[6].source = vertexList.get(3);
edges[6].destination = vertexList.get(1);
edges[6].weight = 1;

// edge 4--> 3
edges[7].source = vertexList.get(4);
edges[7].destination = vertexList.get(3);
edges[7].weight = -3;


Graph graph = new Graph(5, 8, edges);
graph.bellmanFord(graph, 0);
}
}