最短路径算法——Dijkstra
例题
PAT_A1003_Emergency
题意:题意:给出N个城市,M条无向边。每个城市都有一定数目的救援小组,所有边的边权已知。现在给出起点和终点,求从起点到终点的最短路径条数及最短路径上的救援小组数目之和。如果有多条最短路径,则输出数目之和最大的。
输入:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
输出:
2 4
1.基于邻接矩阵实现
java
2.基于邻接表实现
java
搜索过程同时记录最短路径长度,最短路径数目、以及最短路径最大点权数
import java.util.*;
public class Main {
static int node_num;
static int edge_num;
static int start;
static int target;
static LinkedList<Edge>[] E1;
static int[] weight;
static boolean[] vis;
static int path_num;
static int team_num;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
node_num = sc.nextInt();
edge_num = sc.nextInt();
start = sc.nextInt();
target = sc.nextInt();
weight = new int[node_num];
for(int i=0;i<node_num;i++) {
weight[i] = sc.nextInt();
}
E1 = new LinkedList[edge_num];
for(int i=0;i<edge_num;i++) {
E1[i] = new LinkedList<Edge>();
}
for(int i=0;i<edge_num;i++) {
int a1 = sc.nextInt();
int a2 = sc.nextInt();
int a3 = sc.nextInt();
E1[a1].add(new Edge(a1,a2,a3));
E1[a2].add(new Edge(a2,a1,a3));
}
Dijkstra(start, target);
System.out.println(path_num);
System.out.println(team_num);
}
static void Dijkstra(int start, int target) {
boolean[] vis = new boolean[node_num];
int[] d = new int[node_num];
Arrays.fill(d, Integer.MAX_VALUE);
d[start]=0; //起点到自身的距离为0
int[] w = new int[node_num];
w[start]=weight[start];
int[] num = new int[node_num];
num[start]=1; //初始化时到达起点的路径数为1!!!
for(int i=0;i<node_num;i++) {
//找出未访问过且距离最小的顶点
int u=-1;
int min= Integer.MAX_VALUE;
for(int j=0;j<node_num;j++) {
if(vis[j]==false&&d[j]<min) {
u = j;
min = d[j];
}
}
if(u==-1) return;
vis[u]=true;
//------------------关键部分----------------
//遍历u可到达的点next
for(int v=0;v<E1[u].size();v++) {
Edge next = E1[u].get(v);
if(vis[next.Q]==false) {//v未访问过
if(next.D+d[u]<d[next.Q]) {
d[next.Q]=next.D+d[u];
w[next.Q]=w[u]+weight[next.Q];
num[next.Q]=num[u];
}
else if(next.D+d[u]==d[next.Q]) {
num[next.Q]+=num[u];
if(w[u]+weight[next.Q]>w[next.Q]) {
w[next.Q]=w[u]+weight[next.Q];
}
}
}
}
}
path_num=num[target];
team_num=w[target];
}
static class Edge{
private int P;
private int Q;
private int D;
Edge(int P,int Q,int D) {
this.P=P;
this.Q=Q;
this.D=D;
}
}
}
易错点:
- 初始化时
d[start]
、w[start]
、num[start]
要初始化为起点的的对应值- 使用Integer.MAX_VALUE当作无穷大