问题描述
给定一个图,图的节点名称用( 0 0 0 ~ N − 1 N - 1 N−1)表示。 N N N为图的节点个数, M M M为边的个数, S S S为起始点。
输入条件:
第一行输入 N M S N M S NMS。
其后 M M M行,每行输入三个数,分别代表源节点、目标节点、边的距离。
输出条件:
请输出 S S S到所有点的最短距离,并打印出每一步经过的节点名称(中间以空格隔开)。
测试样例:
输入:
4 5 0
0 1 1
1 3 2
0 3 4
0 2 2
2 3 1
输出:
从 0 到 0 的最短距离是:0
所经过的路径是:
0
-----------------------------------
从 0 到 1 的最短距离是:1
所经过的路径是:
0 1
-----------------------------------
从 0 到 2 的最短距离是:2
所经过的路径是:
0 2
-----------------------------------
从 0 到 3 的最短距离是:3
所经过的路径是:
0 1 3
-----------------------------------
输入:
5 8 0
0 1 10
0 3 20
0 4 100
1 2 10
2 4 10
3 2 10
3 4 10
1 4 20
输出:
从 0 到 0 的最短距离是:0
所经过的路径是:
0
-----------------------------------
从 0 到 1 的最短距离是:10
所经过的路径是:
0 1
-----------------------------------
从 0 到 2 的最短距离是:20
所经过的路径是:
0 1 2
-----------------------------------
从 0 到 3 的最短距离是:20
所经过的路径是:
0 3
-----------------------------------
从 0 到 4 的最短距离是:30
所经过的路径是:
0 1 4
-----------------------------------
算法就不介绍了,慕课浙大数据结构讲的很好。
迪杰斯特拉算法能处理有权单源图的最短路径问题(边权重不能有负值)。
代码思路
- 建立邻接数组(邻接链表),并根据已知数据填充数组。
- 根据题目需求,建立
checked
数组、dist
数组、path
数组、count
数组来分别保存节点是否被访问过、最短距离、上一跳、路线个数。并对这些数组做初始化。 - 进入大循环,找到一个未处理过,而且具有最小边的节点
i
(dist[i]
最小)。可以通过小顶堆来维护最小的边,也能直接遍历所有节点找出最小边。
- 如果找不到,说明图已经处理完了,直接退出。
- 如果找到了,将
check[i]
设为已访问。并访问其相邻节点。 - 遍历相邻节点
j
时,如果从起始点到i
,再从i
到j
的距离比直接从起始点到j
的距离短的话,更新起始点到j
的距离,并将j
的上一跳设置为i
。 - 最后得到的
dist
数组,保存了起始点到所有点的最短距离。path
数组保存了从起始点到所有点最短路径的上一跳。根据题目要求输出即可。
代码模板
import java.util.Arrays;
import java.util.Scanner;
/**
* @Auther: Erekilu
* @Date: 2020-06-04
*/
public class Dijkstra
{
private static final int MAX = 0x3f3f3f3f;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int count = in.nextInt();
int number = in.nextInt();
int source = in.nextInt();
int[][] line = new int[number][3];
for (int i = 0 ; i < number ; i++)
{
line[i][0] = in