0图中等 NC158 单源最短路

NC158 单源最短路

描述

在一个有 nn 个点, mm 个边的有向图中,已知每条边长,求出 11 到 nn 的最短路径,返回 11 到 nn 的最短路径值。如果 11 无法到 nn ,输出 -1−1 图中可能有重边,无自环。

普通迪杰斯特拉(Dijkstra)算法解法

  • 基本思想:所有点分为两个集合S和U,以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止
  • 实现步骤如下:
  1. 计算起始节点到U中每一个节点的路径长度,选择其中路径最短的点加入S。
  2. 借助上一步刚加入S的点,更新U中每个点到S的距离。
  3. 重复步骤1,2,直到所有的点都加入到S当中。
  • 整个过程需要一个二维数组来明确每个点到其他点的距离。
  • 二维数组的每个元素需要初始化为Integer.MAX_VALUE,方便寻找最短路径
  • 需要一个一维数组来区分这个点是在S当中还是U当中。
  • 也有人专门建了一个一维数组,用来标记其他点到起始点的最短距离,我选择重复利用上面已经建立的二维数组。
  • 可以使用小顶堆减少一次循环,降低时间复杂度。
    看不懂了可以参考这几篇博客:
    Dijkstra算法(一)之 C语言详解
    dijkstra算法求单源最短路径 java版本
import java.util.*;
public class Solution {
    public int findShortestPath (int n, int m, int[][] graph) {
        boolean[] flag = new boolean[n];
        flag[0] = true;
        int[][] dis = new int[n][n];
        //二维数组不可以使用Arrays.fill赋值。
        //Arrays.fill(dis,-1);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                dis[i][j] = Integer.MAX_VALUE;
            }
        }
        for(int i = 0; i < m; i++){
            int a = graph[i][0]-1;
            int b = graph[i][1]-1;
            int c = graph[i][2];
            dis[a][b] = Math.min(dis[a][b],c);//取最小值防止有重边
            //dis[b][a] = Math.min(dis[b][a],c);添上这行代码不能ac,不明白为什么?
        }

        for(int i = 1; i < n; i++){
            int min = Integer.MAX_VALUE;
            int k = -1;
            for(int j = 0; j < n; j++){
                if(flag[j] == false && dis[0][j] < min){
                    min = dis[0][j];
                    k = j;
                }
            }
            if(k == -1){
                break;
            }
            flag[k] = true;
            for(int j = 0; j < n; j++){
                //判断dis[k][j] != Integer.MAX_VALUE是为了防止int temp = min + dis[k][j]越界
                if(flag[j] == false && dis[k][j] != Integer.MAX_VALUE){
                    int temp = min + dis[k][j];
                    dis[0][j] = Math.min(dis[0][j],temp);
                }
            }
        }
        if(dis[0][n-1] == Integer.MAX_VALUE){
            return -1;
        }
        return dis[0][n-1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值