PAT(甲级)Java 1003 Emergency (25 分) Dijkstra算法

参考文章:https://www.liuchuo.net/archives/2359
思路看参考文章

一遍Dijkstra算法,用Dijkstra求边权最小的最短路径的条数,以及这些最短路径中点权最大的值。
rescue_queue[]-保存点权(救援队数目)
dis[i] -保存源点到i结点的最短路径
w[i]- 保存最大救援队数目
num[i]-保存从源点到i结点的最短路径个数

若 dis[u] + e[u][v] <dis[v],更新dis[v],同时更新num[v]=num[u],w[v]= rescue_queue [v] +w[u];
如果dis[u] + e[u][v] == dis[v],还要更新num[v] +=num[u],而且判断一下是否权重w[v]更小,如果更小了就更新w[v] = rescue_queue [v] + w[u];

package pat;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 参考文章:https://www.liuchuo.net/archives/2359
 * 
 * @author Charlie Yang
 *  1、Dijkstra算法 -- 单源点最短路径问题
 *  2、dis[i] -保存源点到i结点的最短路径 ,
 *     w[i]- 保存最大救援队数目 ,
 *     num[i]-保存从源点到i结点的最短路径个数
 * 
 */
public class Main{

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int city = input.nextInt();// 城市数
		int road = input.nextInt();// 道路数
		int current = input.nextInt();// 当前城市
		int destination = input.nextInt();// 目的地
		input.nextLine();
		String[] rescue = input.nextLine().split(" ");
		int[] rescue_queue = new int[rescue.length];// 救援队数组,保存救援队数目
		for (int i = 0; i < rescue.length; i++) {
			rescue_queue[i] = Integer.parseInt(rescue[i]);
		}
//		System.out.println(Arrays.toString(rescue_queue));
		int[] dis = new int[city];
		int[] w = new int[city];
		int[] num = new int[city];
		int[][] e = new int[city][city]; // 边集
		boolean[] vis = new boolean[city];
		final int inf = 99999999;
		Arrays.fill(vis, false);
		Arrays.fill(num, 0);
		Arrays.fill(dis, inf);
		for (int i = 0; i < city; i++) {
			Arrays.fill(e[i], inf);
		}
		for (int i = 0; i < road; i++) {
			int fi, sec, adj;
			fi = input.nextInt();
			sec = input.nextInt();
			adj = input.nextInt();
			e[fi][sec] = e[sec][fi] = adj;
		}
		dis[current] = 0;
		w[current] = rescue_queue[current];
		num[current] = 1;

		for (int i = 0; i < city; i++) {
			int u = -1, minn = inf;
			for (int j = 0; j < city; j++) {
				if (vis[j] == false && dis[j] < minn) {
					u = j;
					minn = dis[j];
				}
			}

			if (u == -1)
				break;
			vis[u] = true;
			for (int v = 0; v < city; v++) {
				if (vis[v] == false && e[u][v] != inf) {
					if (dis[u] + e[u][v] < dis[v]) {
						dis[v] = dis[u] + e[u][v];
						num[v] = num[u];
						w[v] = w[u] + rescue_queue[v];
					} else if (dis[u] + e[u][v] == dis[v]) {
						num[v] = num[v] + num[u];
						if (w[u] + rescue_queue[v] > w[v])
							w[v] = w[u] + rescue_queue[v];
					}
				}
			}

		}
		
		System.out.printf("%d %d",num[destination],w[destination]);
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值