• 数据结构与算法


    Dijkstra 求最短路

    acwing上有位博主的解析非常哈

    求源点到其余各点的最短距离步骤如下:

    用一个 dist 数组保存源点到其余各个节点的距离,dist[i] 表示源点到节点 i 的距离。初始时,dist 数组的各个元素为无穷大。
    用一个状态数组 state 记录是否找到了源点到该节点的最短距离,state[i] 如果为真,则表示找到了源点到节点 i 的最短距离,state[i] 如果为假,则表示源点到节点 i 的最短距离还没有找到。初始时,state 各个元素为假。


    源点到源点的距离为 0。即dist[1] = 0。


    遍历 dist 数组,找到一个节点,这个节点是:没有确定最短路径的节点中距离源点最近的点。假设该节点编号为 i。此时就找到了源点到该节点的最短距离,state[i] 置为 1。


    遍历 i 所有可以到达的节点 j,如果 dist[j] 大于 dist[i] 加上 i -> j 的距离,即 dist[j] > dist[i] + w[i][j](w[i][j] 为 i -> j 的距离) ,则更新 dist[j] = dist[i] + w[i][j]。


    重复 3 4 步骤,直到所有节点的状态都被置为 1。


    此时 dist 数组中,就保存了源点到其余各个节点的最短距离。

     题目

    给定一个 nn 个点 mm 条边的有向图,图中可能存在重边和自环,所有边权均为正值。

    请你求出 11 号点到 nn 号点的最短距离,如果无法从 11 号点走到 nn 号点,则输出 −1−1。

    输入格式

    第一行包含整数 nn 和 mm。

    接下来 mm 行每行包含三个整数 x,y,zx,y,z,表示存在一条从点 xx 到点 yy 的有向边,边长为 zz。

    输出格式

    输出一个整数,表示 11 号点到 nn 号点的最短距离。

    如果路径不存在,则输出 −1−1。

    数据范围

    1≤n≤5001≤n≤500,
    1≤m≤1051≤m≤105,
    图中涉及边长均不超过10000。

    代码1

    1. import java.util.Arrays;
    2. import java.util.Scanner;
    3. public class Main {
    4. //从这里看,边是比较多的,所有可以用邻接矩阵存数据
    5. static int N = 510;
    6. static int m, n;
    7. static int[][] g = new int[N][N];
    8. static int[] dist = new int[N];
    9. static boolean[] st = new boolean[N];
    10. //注意:有向图和无向图相比,无向图可以看出有向图
    11. //如果有重边,保留距离最短的那条边
    12. public static void main(String[] args) {
    13. Scanner sc = new Scanner(System.in);
    14. n = sc.nextInt(); m = sc.nextInt();
    15. for (int i = 1; i <= n; i++) Arrays.fill(g[i], 0x3f3f); //权值不超过10000
    16. while (m-- > 0) {
    17. int a = sc.nextInt(), b = sc.nextInt(), c = sc.nextInt();
    18. g[a][b] = Math.min(g[a][b], c);
    19. }
    20. // 表示1号点到n号点的最短距离
    21. System.out.println(dijkstra());
    22. }
    23. private static int dijkstra() {
    24. Arrays.fill(dist, 0x3f3f);
    25. dist[1] = 0; //把自己的距离设置为 0
    26. //遍历一遍 找到一个最小的点,加入到集合中,这里加入到集合里,是通过st来做
    27. //迭代n次,n次迭代后获得最终结果集
    28. for (int i = 0; i < n; i++) {
    29. int t = -1; //表示还没有最短的点
    30. for (int j = 1; j <= n; j++) {
    31. if (!st[j] && (t == -1 || dist[t] > dist[j])) {
    32. t = j;
    33. }
    34. } //循环后找到了最短的点,为 t
    35. st[t] = true; // t 加进结果集中
    36. //最后拿 t 更新一下结果集
    37. for (int j = 1; j <= n; j++) dist[j] = Math.min(dist[j], dist[t] + g[t][j]);
    38. }
    39. if (dist[n] == 0x3f3f) return -1;
    40. else return dist[n];
    41. }
    42. }

    代码2

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N=510;
    6. int g[N][N]; //为稠密阵所以用邻接矩阵存储
    7. int dist[N]; //用于记录每一个点距离第一个点的距离
    8. bool st[N]; //用于记录该点的最短距离是否已经确定
    9. int n,m;
    10. int Dijkstra()
    11. {
    12. memset(dist, 0x3f,sizeof dist); //初始化距离 0x3f代表无限大
    13. dist[1]=0; //第一个点到自身的距离为0
    14. for(int i=0;i//有n个点所以要进行n次 迭代
    15. {
    16. int t=-1; //t存储当前访问的点
    17. for(int j=1;j<=n;j++) //这里的j代表的是从1号点开始
    18. if(!st[j]&&(t==-1||dist[t]>dist[j]))
    19. t=j;
    20. st[t]=true;
    21. for(int j=1;j<=n;j++) //依次更新每个点所到相邻的点路径值
    22. dist[j]=min(dist[j],dist[t]+g[t][j]);
    23. }
    24. if(dist[n]==0x3f3f3f3f) return -1; //如果第n个点路径为无穷大即不存在最低路径
    25. return dist[n];
    26. }
    27. int main()
    28. {
    29. cin>>n>>m;
    30. memset(g,0x3f,sizeof g); //初始化图 因为是求最短路径
    31. //所以每个点初始为无限大
    32. while(m--)
    33. {
    34. int x,y,z;
    35. cin>>x>>y>>z;
    36. g[x][y]=min(g[x][y],z); //如果发生重边的情况则保留最短的一条边
    37. }
    38. cout<<Dijkstra()<
    39. return 0;
    40. }

  • 相关阅读:
    Javasript中的BOM
    进程与线程
    MyBatisPlus(十二)排序查询:orderBy
    word 列项处理
    mysql数据库表之间关系,一对一、一对多、多对多,多表查询
    【bug优化】Three.js 中实现圆角立方体的详尽指南
    x汽车登陆网站登陆rsa加密逆向
    spring boot+MySQL婚纱影楼管理系统vue
    MIT6.S081的gdb调试方法
    使用QGIS转换矢量数据投影
  • 原文地址:https://blog.csdn.net/m0_66057675/article/details/126206434