算法步骤如下:贪心思想

这里默认1为起点,且每一轮必定找出一个其他点到1点的最短路径,那么将在n-1轮后找到所有点到1点的最短路径。

  1. 找出与 1 直接相邻的点,在这些邻点与 1 组成的边中选择权值最小的一条边
  2. 将第一步中选中的邻点与 1 点的连接关系改为不相邻,而将通过该邻点可以与 1 点进行连接的点与 1 点的连接关系改为相邻(如果本身这个点与 1 点就是相邻的,那么我们就要判断哪个原来的权值与通过邻点连接的边的权值的大小了)。1 点与这些后来连接上的邻点所构成的边的权值为:
    1 点与中间邻点的边的权值 + 中间邻点和新连接的邻点所构成的边的权值

不断重复这个过程即可。


代码如下:

#include<iostream>
#include<cstring>
using namespace std;
/*最短路径算法: Dijkstra算法图的存储结构: 邻接矩阵(二维数组),当然也可以邻接表(一维数组 + 链表),这里用的邻接矩阵。这里默认是无向图
*/
int pointNum;                    //点的个数, 当然点从1开始
int lineNum;                     //边的个数
int begin=1, goal=1;             //起始点,目标点
int Graph[2022][2022];               //用二维数组来表示图,Graph[1][2] = 6, 表示点1与2之间存在边,且这条边的权值为6.  不存在边记为-1, 该边已经计算过了记为-2
int path[2022];                    //记录沿途路径, path[2] = 1, 表示在最短路径中,2点的前一个点是1.
/*path举例说明: 如我们得出的一条由 1点 为源点到 4点 的最短路径为 1 -> 2 -> 4那么就会有: path[4] = 2     、  path[2] = 1*/
int weight[2022];                  //记录由初始点到每个点的最短路径的权值
void Dijkstra();
void Input();
void Output();
int main()
{Input();Dijkstra();Output();return 0;
}void Input()
{cout<<"请输入点的个数(点的个数小于2021): "; cin>>pointNum;cout<<"请输入边的个数: ";cin>>lineNum;cout<<"请输入起点: "; cin>>goal;                            //这里将begin和goal倒置,方便输出cout<<"请输入目标点: "; cin>>begin;int n,m,w;int k=1;memset(Graph,-1,sizeof(Graph));for(int i=0; i<lineNum; i++){cout<<"依次输入无向边边的两个顶点和权值: ";cin>>n>>m>>w;Graph[n][m] = w;Graph[m][n] = w;if(n==begin){path[m] = begin;}else if(m==begin){path[n] = begin;}}
}void Dijkstra()
{path[begin] = begin;weight[begin] = 0;for(int i=0; i<pointNum-1; i++){int j;int minWeight = 999999999;   //默认所有边权值总和不超过10亿int point = -1;for(j=1;j<=pointNum;j++){if(j!=begin && Graph[begin][j]>0){if(minWeight > Graph[begin][j]){minWeight = Graph[begin][j];point = j;}}}weight[point] = minWeight;for(j=1;j<=pointNum;j++){if(j!=begin && j!=point && Graph[point][j]!=-1){if(Graph[begin][j] == -1){Graph[begin][j] = Graph[begin][point] + Graph[point][j];path[j] = point;}else if(Graph[begin][j] > (Graph[begin][point] + Graph[point][j])){Graph[begin][j] = Graph[begin][point] + Graph[point][j];path[j] = point;}}}Graph[begin][point] = -2;Graph[point][begin] = -2;if(point == goal)        //已经找到起点到目标点的最短路径,直接结束即可,无需继续进行,当然你也可以不结束,全部运行完后也能获得输出结果{break;}}
}void Output()
{cout<<"最短路径的权值为: "<<weight[goal]<<endl;int n = path[goal];cout<<"路径为: "<<endl;cout<<goal<<" -> "<<n;while(n != begin){              cout<<" -> "<<path[n];n=path[n];}cout<<endl;
}

简要分析:

如果一个无相图有n个点,m条边,且这个无向图是连通图,那么至少有n-1条边。
Bellman-Ford算法/SPFA算法对于最短路径问题的时间复杂度为o(m * n)。
Dijkstra算法对于最短路径问题的时间复杂度为o(n * n),由于m>n-1,且m最大为n*(n-1),因此单论时间复杂度来讲,Dijkstra算法要更优。
如果你十分了解Dijkstra算法,那么会知道这个算法是可以进行堆优化的(每次找当前这一轮权值最小的边,使用小根堆优化),使得时间复杂度达到o(n*log₂n)。

Dijkstra算法缺点也很明显,不能有负权值的边。而Bellman-Ford算法/SPFA算法只需要没有负权值回路即可。


例题: 蓝桥杯省赛2020填空题

小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。
小蓝的图由2021个结点组成,依次编号1至2021。
对于两个不同的结点a, b,如果a和b的差的绝对值大于21,则两个结点之间没有边相连;如果a和b的差的绝对值小于等于21,则两个点之间有一条长度为a和b的最小公倍数的无向边相连。
例如∶结点1和结点23之间没有边相连;结点3和结点24之间有一条无向边,长度为24;结点15和结点25之间有一条无向边,长度为75。
请计算,结点1和结点2021之间的最短路径长度是多少。
提示:建议使用计算机编程解决问题。

思路: 最短路径算法 + 辗转相除法
代码如下:

#include<iostream>
#include<cstring>
using namespace std;
/*最短路径算法: Dijkstra算法图的存储结构: 邻接矩阵(二维数组),当然也可以邻接表(一维数组 + 链表),这里用的邻接矩阵。这里默认是无向图
*/
int pointNum;                    //点的个数, 当然点从1开始
int begin, goal;             //起始点,目标点
int Graph[2022][2022];               //用二维数组来表示图,Graph[1][2] = 6, 表示点1与2之间存在边,且这条边的权值为6.  不存在边记为-1, 该边已经计算过了记为-2
int path[2022];                    //记录沿途路径, path[2] = 1, 表示在最短路径中,2点的前一个点是1.
/*path举例说明: 如我们得出的一条由 1点 为源点到 4点 的最短路径为 1 -> 2 -> 4那么就会有: path[4] = 2     、  path[2] = 1*/
int weight[2022];                  //记录由初始点到每个点的最短路径的权值
void Initialization();
void Dijkstra();
void Output();
int GetLeastCommonMultiple(int num1,int num2);
int main()
{Initialization();Dijkstra();Output();return 0;
}void Initialization()
{int i,j,k;pointNum = 2021; goal = 1; begin = 2021;memset(Graph,-1,sizeof(Graph));for(i=1;i<=2021;i++){if(i-21>0 && i+21<=2021){ j = i-20; k = 21;}else if(i-21<0){j = 1;k = 21;}else if(i+21>2021){j = i-20;k = 2021-i;}for(j=i;j<=i+k;j++){if(j!=i){Graph[i][j] = GetLeastCommonMultiple(j,i);Graph[j][i] = Graph[i][j];if(i==begin){path[j] = i;}else if(j==begin){path[i] = j;} }}}
}int GetLeastCommonMultiple(int num1,int num2)
{int n1 = num1, n2 = num2 ,exchange;int MaximumCommonFactor = -1;while(1){if(n1%n2 == 0){MaximumCommonFactor = n2;break;}else{exchange = n1;n1 = n2;n2 = exchange%n2;}}return num1*num2/MaximumCommonFactor;
}void Dijkstra()
{path[begin] = begin;weight[begin] = 0;for(int i=0; i<pointNum-1; i++){int j;int minWeight = 999999999;   //默认所有边权值总和不超过10亿int point = -1;for(j=1;j<=pointNum;j++){if(j!=begin && Graph[begin][j]>=0){if(minWeight>Graph[begin][j]){minWeight = Graph[begin][j];point = j;}}}weight[point] = minWeight;for(j=1;j<=pointNum;j++){if(j!=begin && j!=point && Graph[point][j]!=-1){if(Graph[begin][j] == -1){Graph[begin][j] = Graph[begin][point] + Graph[point][j];path[j] = point;}else if(Graph[begin][j] > (Graph[begin][point] + Graph[point][j])){Graph[begin][j] = Graph[begin][point] + Graph[point][j];path[j] = point;}}}Graph[begin][point] = -2;Graph[point][begin] = -2;if(point == goal)        //已经找到起点到目标点的最短路径,直接结束即可,无需继续进行,当然你也可以不结束,全部运行完后也能获得输出结果{break;}}
}void Output()
{cout<<"最短路径的权值为: "<<weight[goal]<<endl;int n = path[goal];cout<<"路径为: "<<endl;cout<<goal<<" -> "<<n;while(n != begin){              cout<<" -> "<<path[n];n=path[n];}cout<<endl;
}
/*最终答案: 10266837
*/


学习记录,喷子绕路

Dijkstra算法以及与其他最短路径算法简要对比相关推荐

  1. dijkstra算法_Dijkstra算法详细(单源最短路径算法)

    介绍 对于 dijkstra 算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解 bfs和dfs ,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原 ...

  2. dijkstra最短路径算法视频_Dijkstra算法详细(单源最短路径算法)

    介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...

  3. 【老生谈算法】matlab实现最短路径算法——最短路径算法

    最短路径算法-matlab程序 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]最短路径算法-matlab程序.doc 2.算 ...

  4. 【算法】【ACM】深入理解Dijkstra算法(单源最短路径算法)

    Dijkstra算法是用来求解从某个源点到其他各顶点的最短路径(单源最短路径). 下面的Dijkstra算法的讲解都是基于这个有向图,在遇到其他问题可以类比. 算法的基本思想: 把图中的定点分成两组, ...

  5. Dijkstra(迪杰斯特拉)算法:单源最短路径算法

    算法目的 以较小的时间复杂度求解加权有向图中一个源点到其余各个点的最短路径. 适用条件 图中不存在负权边.(否则,原点到原点的距离为0却不是最近的,显然违背了逻辑) 算法原理 将加权有向图中的点分为S ...

  6. 用java编写的一个迪杰斯特拉算法(单源最短路径算法,Dijkstra算法)。

    可以用于有向图和无向图.用负数表示该有向路不通.在EditPlus上写的,所以就一个.java文件. package Test;import java.util.TreeMap; import jav ...

  7. 【老生谈算法】matlab实现最短路径算法源码——最短路径算法

    每对顶点之间的最短路径 matlab程序 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]最短路径的Floyd算法的Matla ...

  8. Codeup 问题 B: 算法7-16:弗洛伊德最短路径算法

    题目描述 在带权有向图G中,求G中的任意一对顶点间的最短路径问题,也是十分常见的一种问题. 解决这个问题的一个方法是执行n次迪杰斯特拉算法,这样就可以求出每一对顶点间的最短路径,执行的时间复杂度为O( ...

  9. Codeup墓地-问题 B: 算法7-16:弗洛伊德最短路径算法

    题目描述 在带权有向图G中,求G中的任意一对顶点间的最短路径问题,也是十分常见的一种问题. 解决这个问题的一个方法是执行n次迪杰斯特拉算法,这样就可以求出每一对顶点间的最短路径,执行的时间复杂度为O( ...

最新文章

  1. 深蓝学院第三章:基于卷积神经网络(CNN)的手写数字识别实践
  2. 执行计划有时不准确_生管如何应对采购物料不及时、回不来?
  3. 石墨烯可提高热成像质量 提高安检准确性
  4. 2018【比特杯】编程大赛
  5. C语言浮点数据在内存中的存储方式
  6. java集合——集合与数组间的转换+算法
  7. Exchange Server 2013系统要求
  8. mysql 堆表_Mysql聚集索引和非聚集索引(堆组织表和索引组织表)
  9. UIButton常用属性
  10. ios换肤思想,及工具类
  11. King Arthur's Birthday Celebration
  12. 联想笔记本键盘排线_笔记本键盘排线怎么拆 thinkpad
  13. html标签中写onclick,HTML a 标签添加 onclick()事件的几种方式
  14. C语言中动态库/静态库的创建和使用
  15. ​Mockplus新年福利来了!见者有份!
  16. 淘宝店铺装修教程之下载淘宝视频及分析视频地址中的高逼格信息
  17. 【IPC通信】key_t键和ftok函数
  18. 2017企业网盘年终盘点|机遇与挑战并存,寡头显现
  19. Kaggle手写数字识别(Digit Recognizer)记录
  20. 《消费者行为学》读书笔记 第一章 消费者行为学导论

热门文章

  1. LCD1602显示屏原理及使用教程
  2. 内网靶场_从自做到拿下-攻击篇
  3. qt向服务器传输文字_使用Qt实现客户端服务端聊天和传输文件
  4. Python+大数据-数据分析与处理(六)-综合案例
  5. 传统方法学习IT已不再适用,快速提升的方法原来是这样
  6. 转:中国人须知道的76个常识
  7. Kademlia算法 理解 总结
  8. 关于VS2017中VB.NET打开重新打开工程后程序设计界面无法显示的问题
  9. 【根据模板导出多sheet表格数据】
  10. 解决Excel 2016无法直接打开文件的问题