最短路径问题—Dijkstra算法及相关例题

本文总结了在解决Dijkstra算法相关问题时的常见模板和思路,包括与DFS结合的应用,以及在实际题目中的变通应用。通过实例分析了如何在紧急情况(Emergency)、旅行计划(Travel Plan)和多路径问题(All Roads Lead to Rome)中运用Dijkstra算法求解最短路径,并考虑点权和边权的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做算法题的时候总是遇到Dijkstra相关的题目,之前虽然学过图论的一些算法,但第一次做这类题时完全不知从何入手。看了一些博客,并且在PAT上折腾了几题后,发现一些常用的模板与套路,因此在这里进行一个总结。关于Dijkstra的理论知识可以参考这篇博客:最短路径问题-Dijkstra算法详解

Dijkstra算法

Dijkstra算法往往和dfs结合在一起考,因此这里给出一个求解基础Dijkstra+dfs相关题目的大致模板:

public class Main {
   
	static int n;    //节点数
	static int m;    //边数
	static int C1;   //起始点
	static int C2;   //终点
	static int[][] e;//边权
	static int[] weight;    //点权(非必需,视题目而定)
	static int[] dis;       //到起始点的最短路径长
	static boolean[] visit; //是否访问过
	static ArrayList<Integer>[] pre;    //可构成最短路径的前一个节点
	static LinkedList<Integer> tempPath = new LinkedList<Integer>();    //可能的最短路径
	static LinkedList<Integer> path = new LinkedList<Integer>();    //最短路径

	public static void main(String[] args) {
   
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		C1 = sc.nextInt();
		C2 = sc.nextInt();
		visit = new boolean[n];
		weight = new int[n];
		for(int i = 0; i < n; i++) {
   
			weight[i] = sc.nextInt();
		}
		e = new int[n][n];
		for(int i = 0; i < n; i++) {
   
			for(int j = 0; j < n; j++) {
   
				e[i][j] = e[j][i] = Integer.MAX_VALUE;
			}
		}
		for(int i = 0; i < m; i++) {
   
			int c1 = sc.nextInt();
			int c2 = sc.nextInt();
			e[c1][c2] = e[c2][c1] = sc.nextInt();
		}
		dis = new int[n];
		for(int i = 0; i < n; i++) {
   
			dis[i] = Integer.MAX_VALUE;
		}
		dis[C1] = 0;
		pre = new ArrayList[n];
		for(int i = 0; i < n; i++) {
   
			pre[i] = new ArrayList<>();
		}
		
		/**************以上为初始化****************/
		
		for(int i = 0; i < n; i++) {
   
			int u = -1, min = Integer.MAX_VALUE;
			for(int j = 0; j < n; j++) {
   
				if(!visit[j] && dis[j] < min) {
   
					min = dis[j];
					u = j;
				}
			}
			if(u == -1) break;
			visit[u] = true;
			for(int v = 0; v < n; v++) {
   
				if(!visit[v] && e[u][v] != Integer.MAX_VALUE) {
   
					if(dis[v] > dis[u] + e[u][v]) {
   
						dis[v] = dis[u] + e[u][v];
						pre[v].clear();
						pre[v].add(u);
					} else if(dis[v] == dis[u] + e[u][v]) {
   
						pre[v].add(u);
					}
				}
			}
		}
		//至此已经找到多个最短路径,下面的dfs算法将在多个最短路径中找到最终解
		dfs(C2);
	}

	private static void dfs(int v) {
   
		tempPath.push(v);
		if(v == C1) {
   
			//此处进行一些判断,在多个最短路径中确认最终解
			tempPath.pop();
			return;
		}
		for(int i = 0; i < pre[v].size(); i++)
			dfs(pre[v].get(i));
		tempPath.pop();
	}
}

Emergency

题目链接:1003 Emergency

此题要求求出两点之间的最短路径,如果存在多条最短路径,那么就选择点权和最大的路径。这里的代码和上面模板几乎一模一样,做题时都需要考虑点权。

public class Main {
   
	private static int n;
	private static int m;
	private static int C1;
	private static int C2;
	private static int[][] e;
	private static int[] weight;
	private static int[] dis;
	private static boolean[] visit;
	private static int max = Integer.MIN_VALUE;
	private static ArrayList<Integer>[] pre;
	private static LinkedList<Integer> tempPath = new LinkedList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值