迪杰斯特拉算法求最短路径(java)

迪杰斯特拉算法求最短路径(java)

    设G=(V,E)是一带权的有向图,源点为v0,则迪杰斯特拉算法用来求v0到其他顶点的最短路径。迪杰斯特拉算法是按路径长度递增的次序产生最短路径的算法
    以此图为例 求v0到v3最短路径的过程
图片1
    dist[3]保存v0到v3的距离,最开始是无限大,即dist[3]=INF,所以迪杰斯特拉算法先找到v2,即dist[2] = 10
图片2
    然后从v2出发,因为v2到v3距离为50(小于INF),即dist[2]+cost[2][3] < dist[3],然后更新dist[3] = 60
图片3
    v0到其他点也是以上步骤,通过与v0相邻的点从而求出其他点的路径。
    下面为代码
输入
6 8
0 2 10
0 4 30
0 5 100
1 2 5
2 3 50
3 5 10
4 3 50
4 5 60
输出
图片
  n为顶点个数,m为可达路径个数,二维数组cost是图的邻接矩阵表示。先把cost初始化为最大值,然后把可达路径依次填入当中。
  这里稍微有点难理解的就是rear数组与q数组,其实稍微模拟一下步骤,就可以很容易理解。
  刚开始初始化的时候,以v2,v3为例
  q[2][0] = 0q[2][1] = 2rear[2] = 2
  q[3][0] = 0q[3][1] = 3rear[3] = 2
  这就相当于刚开始v0到v2的路径为0->2,v0到v3的路径为0->3
  之后更新的时候,因为v0到v3需要经过v2,所以
  q[3][0] = 0q[3][1] = 2q[3][2] = 3rear[3] = 3
  然后输出路径0->2->3

import java.util.Arrays;
import java.util.Scanner;

public class Dijkstra1 {
    public static void main(String args[]){
        Scanner scanner = new Scanner(System.in);
        int n =  scanner.nextInt();
        int m = scanner.nextInt();
        int[][] cost = new int[n][n];
        for(int i = 0; i<n; i++){
            Arrays.fill(cost[i], Integer.MAX_VALUE);
        }
        for(int i = 0; i<m; i++){
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            int p = scanner.nextInt();
            cost[x][y] = p;
        }
        dijkstral(cost, 0, n);
    }
    public static void dijkstral(int[][] cost, int v, int n){
        int[] dist = new int[n];  //保存v到其他点的最短距离
        int[] s = new int[n];  //保存已计算过的顶点
        int[] rear = new int[n];  //rear[i]保存v到顶点i的最短路径顶点数
        int[][] q = new int[n][n];  //q[v][i]保存v到i的最短路径

        //初始化s和rear
        for(int i = 1; i<n; i++){
            s[i] = 0;
            rear[i] = -1;
        }
        //初始化dist和q
        for(int i = 1; i<n; i++){
            dist[i] = cost[v][i];
            if(dist[i] < Integer.MAX_VALUE){
                q[i][++rear[i]] = v;
                q[i][++rear[i]] = i;
            }
        }
        s[v] = 1;
        int j, min, m;
        for(int i = 0; i<n-1; i++){
            min = Integer.MAX_VALUE;
            m = v;
            //寻找和v相邻的最短距离的点
            for(j = 1; j<n; j++){
                if(dist[j] < min && s[j] == 0){
                    min = dist[j];
                    m = j;
                }
            }
            if(m != j){
                s[m] = 1;
                System.out.println(v + "到" + m + "的最短距离为" + dist[m]);
                System.out.print("最短路径为: ");
                for(int k = 0; k<=rear[m]; k++){
                    if(k == rear[m]) {
                        System.out.print(q[m][k]);
                        break;
                    }
                    System.out.print(q[m][k] + "->");
                }
                System.out.println();
                //更新dist,就是上面所说的从v2出发
                for(int k = 1; k<n; k++){
                    if(dist[k] > (cost[m][k] + dist[m]) && s[k] == 0 && cost[m][k] != Integer.MAX_VALUE){
                        dist[k] = cost[m][k] + dist[m];
                        for(int k1 = 0; k1<=rear[m]; k1++){  //更新路径
                            q[k][k1] = q[m][k1];
                        }
                        rear[k] = rear[m];
                        q[k][++rear[k]] = k;
                    }
                }
            }
        }
    }
}
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值