一、原理
目的: 求某点到其它所有点的最短距离
三类集合: 确定了最短路的节点集合A、正在计算最短路的节点集合B、还未进行计算最短路节点的集合C。
大概流程:
- 集合A为空,集合B只有初始节点
- 从初始节点找到所有相邻节点,这些相邻节点加入集合B,初始节点加入A。
- 从集合B中找到距离初始节点最近的节点,从集合A之外的节点中找这个节点所有相邻节点,相邻节点加入集合B,该节点加入集合A
- 循环上一步直至所有节点加入集合A
二、应用与例题
力扣743 单源最短路,求最短路中的最大值
public class Dijkstra743 {
private final static int INF = 0x3f3f3f3f;
int[] dis;
int[] vis;
int[][] cost;
private void dijkstra(int n) {
while (true) {
int next = -1;
for (int i = 1; i <= n; i++) {
if (vis[i] == 0 && (next == -1 || dis[next] > dis[i])) {
next = i;
}
}
if (next == -1) {
break;
}
vis[next] = 1;
for (int i = 1; i <= n; i++) {
if (vis[i] == 0) {
dis[i] = Math.min(dis[i], dis[next] + cost[next][i]);
}
}
}
}
private int calculate() {
int res = 0;
for (int i = 1; i < dis.length; i++) {
if (dis[i] == INF) {
return -1;
}
res = Math.max(res, dis[i]);
}
return res;
}
private void init(int[][] times, int n, int k) {
dis = new int[n + 1];
vis = new int[n + 1];
Arrays.fill(dis, INF);
dis[k] = 0;
cost = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cost[i][j] = INF;
if (i == j) {
cost[i][j] = 0;
}
}
}
for (int[] time : times) {
cost[time[0]][time[1]] = time[2];
}
}
public int networkDelayTime(int[][] times, int n, int k) {
init(times, n, k);
dijkstra(n);
return calculate();
}
public static void main(String[] args) {
Dijkstra743 bellmanFord743 = new Dijkstra743();
System.out.println(bellmanFord743.networkDelayTime(new int[][]{{2, 1, 1}, {2, 3, 1}, {3, 4, 1}}, 4, 2));
}
}
POJ - 1847Tram dijkstra
Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch.
建图,点与相连的第一个点边值为0,与其他点相连为1,与不相连点的边为INF。
用dijkstra直接求。
#include<queue>
#include<stdio.h>
#include<string>
#include<iostream>
#include<map>
#include<limits>
#include<math.h>
using namespace std;
#define N 1000
#define LL long long int
#define pow(a) ((a)*(a))
#define INF 0x3f3f3f3f
#define mem(arr,a) memset(arr,a,sizeof(arr))
int n, a, b;
int cost[N][N];
int vis[N];
int d[N];
void dijkstra(){
mem(d, INF);
mem(vis, 0);
d[a] = 0;
int cnt = 0;
while (1){
cnt++;
int v = -1;
for (int i = 1; i <= n; i++){
if (!vis[i] && (v == -1 || d[i] < d[v]))v = i;
}
if (v == -1)break;
vis[v] = 1;
for (int i = 1; i <= n; i++){
if (d[i]>d[v] + cost[v][i]){
d[i] = d[v] + cost[v][i];
}
}
}
if (d[b]!=INF)
cout << d[b] << endl;
else cout << -1 << endl;
}
int main(){
cin >> n >> a >> b;
mem(cost, INF);
for (int i = 1; i <= n; i++){
int t; cin >> t;
int to; cin >> to;
cost[i][to] = 0;
for (int j = 1; j < t; j++){
cin >> to;
cost[i][to] = 1;
}
}
dijkstra();
}