dijkstra
简介
dijkstra算法是单源最短路径算法。
单源即在一个有向图中,从一个节点出发,算法可求该节点至所有可到达节点的最短路径长度。与之相对的称为非单源最短路,即算法运行一次可求出任意节点至任意可到达节点的最短路长度,其代表是floyd算法。单源最短路有两种常见算法,dijkstra算法和bellman-ford算法。前者只能用于求路径权值全部为非负数的最短路,后者是可以求边权中出现负数的算法。
算法步骤
- 将图中的点分为两组,遍历到的为一组s,没有遍历的为另一组t,当前遍历未开始,所以所有节点都在t中
- 将出发节点的距离设置为0,其他节点到出发节点的距离设置为无穷大
- 寻找在t中寻找距离最少的点,使用该点到其他节点的距离来更新其他节点到出发节点的最短距离,每次更新将该点从t取出,放入s
- 当所有点更新完毕后,出发节点到每个节点的最短距离也就找到了。
算法实现1
时间复杂度为O(n^2)
import java.util.*;
public class Main{
public static final int N = 510;
public static int[][] gra = new int[N][N];
public static int[] dist = new int[N];
public static boolean[] isu = new boolean[N];
//用于记录最短路径
public static int[] path = new int[N];
public static int dijkstra(int begin,int end){
dist[begin] = 0;
for(int i = 1; i <= end; i++){
int t = -1;
for(int j = 1; j <= end; j++){
if(!isu[j] && (t == -1 || dist[t]>dist[j])){
t = j;
}
}
isu[t] = true;
for(int j = 1; j <= end; j++){
if(dist[j] > dist[t]+gra[t][j]){
dist[j] = dist[t]+gra[t][j];
path[j] = t;
}
}
}
if(dist[end] == 0x3f3f3f3f) return -1;
else return dist[end];
}
public static void main(String[] args){
Scanner Reader = new Scanner(System.in);
for(int i = 0;i < gra.length;i++){
Arrays.fill(gra[i],0x3f3f3f3f);
}
Arrays.fill(dist,0x3f3f3f3f);
Arrays.fill(path,-1);
int n = Reader.nextInt(),m = Reader.nextInt();
while(m-- != 0){
int a = Reader.nextInt(),b = Reader.nextInt(),c = Reader.nextInt();
gra[a][b] = Math.min(gra[a][b],c);
}
System.out.print(dijkstra(1,n));
for(int i = 1; i <= n;i++){
System.out.println(path[i]);
}
}
}
算法实现2
由于上述算法每次寻找dist[]的最小值都需要O(n)的时间复杂度,所以我们可以用最小堆保存该图的dist数组,时间复杂度优化为O(m*logn)
import java.util.*;
class Pair implements Comparable<Pair>{
public int first;
public int second;
public Pair(int f,int s){
first = f;
second = s;
}
@Override
public int compareTo(Pair p){
return this.second-p.second;
}
@Override
public String toString(){
return first+" " + second;
}
}
class Graph{
private final int N = 100100;
private int[] e,ne,h,w,dist;
private int idx = 0;
private boolean[] isu = new boolean[N];
private PriorityQueue<Pair> heap = new PriorityQueue();
public Graph(){
e = new int[N];
ne = new int[N];
h = new int[N];
w = new int[N];
dist = new int[N];
Arrays.fill(ne,-1);
Arrays.fill(h,-1);
Arrays.fill(dist,0x3f3f3f3f);
}
public void add(int a, int b, int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
public int dijkstra(int n){
dist[1] = 0;
Pair pt = new Pair(1,0);
heap.offer(pt);
while(!heap.isEmpty()){
Pair pte = heap.poll();
int te = pte.first;
int distance = pte.second;
if(!isu[te]){
isu[te] = true;
for(int j = h[te];j!= -1;j = ne[j]){
dist[e[j]] = Math.min(dist[e[j]],dist[te]+w[j]);
Pair np = new Pair(e[j],dist[e[j]]);
heap.offer(np);
}
}
}
if(dist[n] == 0x3f3f3f3f){
return -1;
}else{
return dist[n];
}
}
}
public class Main{
public static void main(String[] args){
Scanner Reader = new Scanner(System.in);
Graph gra = new Graph();
int n = Reader.nextInt(),m = Reader.nextInt();
while(m-- != 0){
int a = Reader.nextInt(),b = Reader.nextInt(),c = Reader.nextInt();
gra.add(a,b,c);
}
System.out.print(gra.dijkstra(n));
}
}