刷题日志--最短路问题 5.22
更新日志
5.23
更新了堆优化的Dijkstra写法
5.22
动脑子好累吖,想打游戏,Apex的KD都1.07了
Heat Wave G
来源:洛谷
链接:https://www.luogu.com.cn/problem/P1339
题目描述
有一个 n 个点 m 条边的无向图,请求出从 s 到 t 的最短路长度。
输入格式
第一行四个正整数 n,m,s,t。
接下来 m 行,每行三个正整数 u,v,w,表示一条连接 u,v,长为 w 的边。
输出格式
输出一行一个整数,表示答案。
样例 #1
样例输入 #1
1 | 7 11 5 4 |
样例输出 #1
1 | 7 |
提示
【数据范围】
对于 100% 的数据,1 ≤ n ≤ 2500,1 ≤ m ≤ 6200,1 ≤ w ≤ 1000。
【样例说明】
5 -> 6 -> 1 -> 4 为最短路,长度为 3+1+3 = 7。
分析
Dijkstra算法的核心是贪心,适用场景是解决单源最短路问题,即一个点到其他所有点的距离。数据结构里讲过,但是我忘了
它先求出一条长度最短的路径,再参照这条长度最短的路径,求出一条长度次短的路径,直至求出所有点到源点的最短路径。
朴素版的Dijkstra算法比较适用于稠密图(当然稀疏图也能做)
对于本题,我们先创建一个二维数组当邻接矩阵,用来存储两点之间的距离,例:map[i][j]表示从i到j有一条长为map[i][j]的边。先将map中的元素全部初始化为0x3f3f3f3f(一个很大的数,10^9级,一般可以用来当做最大值),随后读入数据,由于可能存在重边,所以我们只需要取最小的边即可。本题是无向图,所以我们需要把两个方向都初始化一下。
之后创建一个一维数组value,用来存储其他点到源点的距离,同样初始化为0x3f3f3f3f,源点到源点的距离初始化为0,之后就是我们的Dijkstra算法了,最外层循环迭代n次,求出所有点到源点的距离,内层循环找当前长度最短的路径,用完之后把它加入到used中。之后用这条最短路径,去更新次短路径,迭代n次之后就求完了所有点到源点的最短路径了。
Code
当然也可以把Dijkstra算法封装成一个函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
int s = scan.nextInt();
int t = scan.nextInt();
int[][] map = new int[n + 1][n + 1];
for (int i = 0; i < n + 1; i++) {
Arrays.fill(map[i], 0x3f3f3f3f);
}
while (m-- > 0) {
int a = scan.nextInt();
int b = scan.nextInt();
int c = scan.nextInt();
map[a][b] = map[b][a] = Math.min(map[a][b], c);
}
boolean[] used = new boolean[n + 1];
int[] value = new int[n + 1];
Arrays.fill(value, 0x3f3f3f3f);
value[s] = 0;
for (int i = 0; i < n; i++) {
int minIndex = -1;
for (int j = 1; j <= n; j++) {
if (!used[j] && (minIndex == -1 || value[j] < value[minIndex]))
minIndex = j;
}
used[minIndex] = true;
for (int j = 1; j <= n; j++) {
value[j] = Math.min(value[j], value[minIndex] + map[minIndex][j]);
}
}
System.out.println(value[t]);
}
}
单源最短路
来源:牛客
链接:戳这里
问题叙述
描述
在一个有 n 个点, m 个边的有向图中,已知每条边长,求出 1 到 n 的最短路径,返回 1 到 n 的最短路径值。如果 1 无法到 n ,输出 -1
图中可能有重边,无自环。
数据范围:1 < n ≤ 50, 1 ≤ m ≤ 5000,1 ≤ dist(n,m) ≤ 1000
示例1
输入:
5,5,[[1,2,2],[1,4,5],[2,3,3],[3,5,4],[4,5,5]]
返回值:
9
示例2
输入:
2,1,[[1,2,4]]
返回值:
4
备注:
两个整数n和m,表示图的顶点数和边数。
一个二维数组,一维3个数据,表示顶点到另外一个顶点的边长度是多少
每条边的长度范围[0,1000]。
注意数据中可能有重边
分析
Code
1 | import java.util.*; |
1 | import java.util.*; |
1 | import java.util.*; |