Dijstra算法是求图中的最短路径,也就是最短路径算法(在有权图(权值非负数)中求从起点到其他节点的最短路径算法。)
它采用的是贪心的思想,每次选择距离最近的地点,也就是说他每一次都是只考虑当前利益并且选定了后续也不能再更改,这样也许会错过总体来说更小的路径
需要注意的是:
- dijkstra 算法可以同时求 起点到所有节点的最短路径
- 权值不能为负数
dijkstra三部曲:
- 第一步,选源点到哪个节点近且该节点未被访问过
- 第二步,该最近节点被标记访问过
- 第三步,更新非访问节点到源点的距离(即更新minDist数组)
代码:
java
import java.util.Arrays;
import java.util.Scanner;
public class dijkstra {
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
int[][] grid=new int[n+1][n+1];
for(int i=0;i<=n;i++){
Arrays.fill(grid[i],Integer.MAX_VALUE);
}
for(int i=0;i<m;i++){
int v=scanner.nextInt();
int u=scanner.nextInt();
int val=scanner.nextInt();
grid[v][u]=val;
}
int[] midDist=new int[n+1];
Arrays.fill(midDist,Integer.MAX_VALUE);
midDist[1]=0;
boolean[] visited=new boolean[n+1];
// 遍历每一个节点,每次循环都会选取一个未访问过的节点
for(int i=1;i<=n;i++){
int minVal=Integer.MAX_VALUE;
int cur=1;
// 第一步选距离原点最近且未访问过的节点
for(int j=1;j<=n;j++){
if(!visited[j]&&midDist[j]<minVal){
minVal=midDist[j];
cur=j;
}
}
// 第二步标记该节点已经访问
visited[cur]=true;
// 第三步更新未访问节点到原点的距离
for(int j=1;j<=n;j++){
if(!visited[j]&&grid[cur][j]!=Integer.MAX_VALUE&&midDist[cur]+grid[cur][j]<midDist[j]){
midDist[j]=midDist[cur]+grid[cur][j];
}
}
}
if(midDist[n]==Integer.MAX_VALUE){
System.out.println(-1);
}else {
System.out.println(midDist[n]);
}
}
}
Bellman_ford算法,仍然是求单源最短路径的。都是先对于上面的Dijstra来说他可以带有权值是负数的边。
Bellman_ford算法的核心思想是 对所有边进行松弛n-1次操作(n为节点数量),从而求得目标最短路。
这里说一下我对松弛的理解:不断尝试通过中间路径来缩短两点间的直线距离
代码如下:
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class Bellman_ford1 {
static class Edge{
int from;
int to;
int val;
public Edge(int from,int to,int val){
this.from=from;
this.to=to;
this.val=val;
}
}
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
List<Edge> edges=new ArrayList<>();
for(int i=0;i<m;i++){
int from=scanner.nextInt();
int to=scanner.nextInt();
int val=scanner.nextInt();
edges.add(new Edge(from,to,val));
}
int[] minDist=new int[n+1];
Arrays.fill(minDist,Integer.MAX_VALUE);
minDist[1]=0;
// 循环n-1次也就是松弛边n-1次
for(int i=1;i<n;i++){
for(Edge edge:edges){
// 确保from已经处理过
if(minDist[edge.from]!=Integer.MAX_VALUE&&(minDist[edge.from]+edge.val)<minDist[edge.to]){
minDist[edge.to]=minDist[edge.from]+edge.val;
}
}
}
if(minDist[n]==Integer.MAX_VALUE){
System.out.println("unconnected");
}else{
System.out.println(minDist[n]);
}
}
}
学习:代码随想录