【算法学习】-【图论】最短路径算法——Dijkstra

最短路径算法——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当作无穷大
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值