最近在做算法题的时候总是遇到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