题目:
求解两个顶点之间的最短路径,比如如下的一张图:
该图对应的点边权重值:
5 8
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4 c
4 5 5
5 3 3
第一行代表5个点,8个边,后面每一行代表两个顶点的连接,以及该边上的权重值,比如第二行是1,2有一条边,边上的权重是2.
解题思路,深度优先遍历可以看之前的文章内容,这里主要讲述广度优先遍历的解法。假如我们还是计算1到5的最短距离。 一开始从1节点进行迭代,这时候迭代的出边节点就是2,5,这时候我们把2(path 2), 5(path 10) 入队,path代表从1到当前节点的路径权重和。
然后对头出队,2出队,2的出边有3 和5,这时候再把3 (path 2 + 3 = 5) 入队,再把 5 (path 2 + 7) 入队,此时对列就是5(path 10), 3( path 5) 5(path 9)
在让头部的5(path 10)出对,因为是计算最短距离,这时候5满足其中一种情况,更新1到5的最短距离,然后不在将5的出边在入队了。
之后让头部的3 (path 5)出队,这时候会把4(path 5 + 4) 入队,对列变为 5 (path 9) , 4 (path 9)
在让头部的5(path 10)出对,因为是计算最短距离,这时候5满足其中一种情况,更新1到5的最短距离,然后不在将5的出边在入队了。
最后把4 (path 9) 出队,把5 (path 9 + 5) 入队,至此对列只剩5(path 14)
最后在让头部的5(path 10)出对,因为是计算最短距离,至此整个对列就为空了。
代码如下:
package graph.path;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayDeque;
import java.util.Queue;
public class TwoVertexShortestPathBFS {
private int[][]matrix;
private int V;
private int E;
// 最短距离
private int twoVertexShortestPath;
class Node {
int startToCurrentPath;
int currentId;
public Node(int path, int id) {
this.startToCurrentPath = path;
this.currentId = id;
}
}
private Queue<Node> queue = new ArrayDeque<>();
public static void main(String[] args) throws Exception {
// 1 buildGraph, 从文件读取图
TwoVertexShortestPathBFS twoVertexShortestPath1 = new TwoVertexShortestPathBFS();
twoVertexShortestPath1.buildGraph("graph/src/main/resources/gpath.txt");
// 2 计算两点最短距离,通过dfs
int twoVertexShortestPathBfs = twoVertexShortestPath1.findTwoVertexShortestPathBfs(1, 5);
System.out.println(twoVertexShortestPathBfs);
twoVertexShortestPathBfs = twoVertexShortestPath1.findTwoVertexShortestPathBfs(2, 1);
System.out.println(twoVertexShortestPathBfs);
twoVertexShortestPathBfs = twoVertexShortestPath1.findTwoVertexShortestPathBfs(2, 5);
System.out.println(twoVertexShortestPathBfs);
}
private void buildGraph(String path) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
String line1 = bufferedReader.readLine();
V = Integer.parseInt(line1.trim().split(" ")[0]);
E = Integer.parseInt(line1.trim().split(" ")[1]);
matrix = new int[V][V];
// 距离权重
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
matrix[i][j] = i == j ? 0 : Integer.MAX_VALUE;
}
}
// 应该读取文件取覆盖具体的权重值
String s;
while ((s = bufferedReader.readLine()) != null) {
String[] line = s.trim().split(" ");
matrix[Integer.parseInt(line[0]) - 1][Integer.parseInt(line[1]) - 1] = Integer.parseInt(line[2]);
}
bufferedReader.close();
}
private int findTwoVertexShortestPathBfs(int start, int end) {
// 一开始最短距离其实赋值为初值
twoVertexShortestPath = matrix[start-1][end-1];
Node node = new Node(0, start-1);
queue.add(node);
while (!queue.isEmpty()) {
Node poll = queue.poll();
if (poll.currentId == end-1) {
// 找到符合终点的值了
twoVertexShortestPath = Math.min(twoVertexShortestPath, poll.startToCurrentPath);
continue;
}
// 通过poll节点,查看邻居节点,append 到Queue
for (int i = 0; i < V; i++) {
if (i != poll.currentId && matrix[poll.currentId][i] != Integer.MAX_VALUE) {
int pollTOIpath = poll.startToCurrentPath + matrix[poll.currentId][i];
if (pollTOIpath > twoVertexShortestPath) {
continue;
}
queue.add(new Node(pollTOIpath, i));
}
}
}
return twoVertexShortestPath;
}
}