1507. 旅行计划 Java代码 (dijkstra求最短路路径和边权最小和)【PAT甲级1030】

58 篇文章 3 订阅
32 篇文章 1 订阅

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出样例:

0 2 3 3 40

算法思路:

在dijkstra更新最短距离时,每更新一次距离,就修改pre数组值,并且修改花费;当原距离与待更新距离相等时,需要对比花费,当花费更小时需要更新,并记录pre数组值。

Java代码: 

import java.io.*;
import java.util.*;

public class Main {
	static int n, m, s, d;
	static final int N= 505, INF  = 0x3f3f3f3f;
	static int [][]g = new int[N][N];
	static int [][]w = new int[N][N];
	static int []pre = new int[N];  //  记录上一步位置
	static int []dis = new int[N];
	static int []sum = new int[N];  // 记录最小花费
	static boolean []vis = new boolean[N];
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] split = br.readLine().split(" ");
		n = Integer.parseInt(split[0]);
		m = Integer.parseInt(split[1]);
		s = Integer.parseInt(split[2]);
		d = Integer.parseInt(split[3]);
		for(int i = 0; i < n; i++) 
			Arrays.fill(g[i], INF);
		
		for(int i = 0; i < m; i++) {
			split = br.readLine().split(" ");
			int a = Integer.parseInt(split[0]);
			int b = Integer.parseInt(split[1]);
			int c = Integer.parseInt(split[2]);
			int d = Integer.parseInt(split[3]);
			g[a][b] = g[b][a] = Math.min(g[a][b], c);
			w[a][b] = w[b][a] = d;
		}
		dijkstra();
		System.out.println(dis[d] + " " + sum[d]);
		
	}
	
	public static void dijkstra() {
		Arrays.fill(dis, INF);
		dis[s] = 0;
		Arrays.fill(pre, -2);
		pre[s] = -1;
		
		for(int i = 0; i < n; i++) {
			int t = -1;
			for(int j = 0; j < n; j++)
				if(!vis[j] && (t == -1 || dis[t] > dis[j]))
					t = j;
			vis[t] = true;
			
			for(int j = 0; j < n; j++) {
				if(dis[j] > dis[t] + g[t][j]) {
					dis[j] = dis[t] + g[t][j];  // 更新距离
					sum[j] = sum[t] + w[t][j];  // 更新花费
					pre[j] = t;  //  记录位置
				}else if(dis[j] == dis[t] + g[t][j]) {
					if(sum[j] > sum[t] + w[t][j]) {
						sum[j] = sum[t] + w[t][j];  // 更改花费
						pre[j] = t;  // 记录位置
					}
				}
			}
		}
		
		int idx = d;
		Stack<Integer> stack = new Stack<>();
		stack.add(d);
		while(pre[idx] != -1) {  // 路径是反着的,先压入栈,再弹出
			int t = pre[idx];
			stack.add(t);
			idx = pre[idx];
		}
		while(!stack.isEmpty())
			System.out.print(stack.pop() + " "); 
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值