最短路问题的三种算法&模板
最短路算法&模板
最短路问题是图论的基础问题。本篇随笔就图论中最短路问题进行剖析,讲解常用的三种最短路算法:Floyd算法、Dijkstra算法及SPFA算法,并给出三种算法的模板。流畅阅读本篇博客需要有图论的基础知识,了解什么是图,什么是最短路,以及一些基本语法知识和算法基础。
1、Floyd算法
我个人认为,Floyd算法是三种最短路算法中最简单、最好理解的算法。它的适用范围是任意两点之间的最短路。这一点是其他两种算法(单源最短路)无法比拟的。它的实现思路也很简单:用三重循环,枚举断点、起始点和终点(注意:顺序千万不能反!!),如果起始点到断点,断点到终点的距离和小于起始点到终点当前状态下的最短路(也就是说找到了一个比它还短的),那么就更新最短路。
它的优点就是简洁明了,易于理解,但是缺点也显而易见,通过它的实现途径,我们可以发现,使用Floyd算法的题一定要用邻接矩阵存图,这样的一个二维数组显然对空间有着要求,一般来讲,只能支持不超过500个点的图,假如更多,便无法支持。同时,Floyd算法还对时间有着要求,因为是三重循环,所以它的时间复杂度是\(O(n^3)\)的,这样的复杂度如果出现在一个复杂程序中,极其容易TLE,所以,请大家使用的时候,一定要读题读题,慎重慎重!
模板:
void Floyd()
{
memset(map,0x3f,sizeof(map));
for(int i=1;i<=n;i++)
map[i][i]=0;
for(int k=1;k<=n;k++)//顺序不要反
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=min(map[i][k]+map[k][j],map[i][j]);
}
2、Dijkstra算法
Dijkstra算法,中文名是迪杰斯特拉算法,简写是DIJ算法。DIJ算法是求解单源最短路,即从某一个源点到达其他所有点的最短路的一个经典算法。它的实现途径也很好理解:我把点分成两个集合,一个是已经扫描过的集合,另一个是没有扫描的集合。即已经确定最短路和没确定最短路的两个集合,用v数组标记。然后我们从没有扫描的集合中挑出一个dist最小的点放入已经扫描的集合中,然后从这个点开始搜索它的所有出边,进行松弛操作即可。
DIJ算法的时间复杂度比较高,大约是\(O(n^2)\)级别的,同SPFA比确实是差了一些,但它有自己独特的优势,由于它的复杂度只和点有关,所以针对于稠密图(边多点少的图),它的求解效率要比SPFA算法高很多。
关于DIJ算法可以使用二叉堆(优先队列)进行优化,即我们常说的DIJ算法堆优化,由于篇幅较长,我放到了另一篇博客中进行讲解,链接:
模板:
void dijkstra(int start)//源点
{
int temp,k,y;
memset(dist,0x3f,sizeof(dist));
memset(v,0,sizeof(v));
dist[start]=0;
for(int i=1;i<=n;i++)
{
temp=1<<30;
for(int j=1;j<=n;j++)
if(dist[j]<temp && v[j]==0)
k=j,temp=dist[j];
v[k]=1;
for(int j=head[k];j;j=nxt[j])
{
y=to[j];
if(dist[y]>dist[k]+val[j])
dist[y]=dist[k]+val[j];
}
}
}
3、SPFA算法
网上有一张热图,就是“关于SPFA,它死了”。但是SPFA并没有死,它不仅活的好好的,还是一种国产算法,更是我最擅长的最短路算法。
SPFA的适用范围同样也是单源最短路,但是它的实现途径较抽象:新建一个队列,保存等待优化的节点,把源点加入队列。取出队首节点x,遍历x的所有出边,进行松弛操作,如果x点的到达点y被更新,且y不在当前队列中,就把y压入队尾。重复直到队列空为止。
SPFA的实现模板跟宽搜很类似,希望大家好好体会。
SPFA的时间复杂度也很优越,根据证明,期望的时间复杂度可以达到\(O(kM)\),其中M为边数,k为所有顶点进队的平均次数。一般来讲,k<=2。
所以我们发现,SPFA算法适用于稀疏图,即点特别多边特别少的图。这和DIJ算法形成了一个对比,希望大家能在做题的时候活学活用。
关于SPFA的算法,有两种优化方式,由于篇幅较长,放在另一个博客中进行讲解。链接如下:
模板:
void spfa(int start)
{
memset(dist,0x3f,sizeof(dist));
memset(v,0,sizeof(v));
queue<int> q;
q.push(start);
v[start]=1;
dist[start]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
v[x]=0;
for(int i=head[x];i;=nxt[i])
{
int y=to[i];
if(dist[y]>dist[x]+val[i])
{
dist[y]=dist[x]+val[i];
if(v[y]==0)
q.push(y),v[y]=1;
}
}
}
}
最短路问题的三种算法&模板的更多相关文章
- c语言求回文数的三种算法的描述
c语言求回文数的三种算法的描述 题目描述 注意:(这些回文数都没有前导0) 1位的回文数有0,1,2,3,4,5,6,7,8,9 共10个: 2位的回文数有11,22,33,44,55,66,77,8 ...
- Java利用DES/3DES/AES这三种算法分别实现对称加密
转载地址:http://blog.csdn.net/smartbetter/article/details/54017759 有两句话是这么说的: 1)算法和数据结构就是编程的一个重要部分,你若失掉了 ...
- 内存分配---FF、BF、WF三种算法
动态分区分配是根据进程的实际需要,动态的为之分配内存空间.而在实现可变分区分配时,将涉及到分区分配中 所用的数据结构.分区分配算法和分区的分配与内存回收的过程. 分区分配中的数据结构:(1)描述空闲块 ...
- 图文实例解析,InnoDB 存储引擎中行锁的三种算法
前文提到,对于 InnoDB 来说,随时都可以加锁(关于加锁的 SQL 语句这里就不说了,忘记的小伙伴可以翻一下上篇文章),但是并非随时都可以解锁.具体来说,InnoDB 采用的是两阶段锁定协议(tw ...
- 【2018寒假集训Day 7】【最短路径】三种算法的模板
Luogu单源最短路径模版题 dijkstra #include<cstdio> #include<vector> using namespace std; const int ...
- HDOJ--1869--六度分离(用三种算法写的,希望能比較出来他们之间的差别)
六度分离 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 常见算法:C语言求最小公倍数和最大公约数三种算法
最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,当中一个最小的公倍数是他们的最小公倍数,相同地,若干个整数公有的倍数中最小的正整数称为它们的最小公倍数,维基百科:定义点击打开链接 求 ...
- C语言求最小公倍数和最大公约数三种算法(经典)
把以前写的一些经验总结汇个总,方便给未来的学弟学妹们做个参考! --------------------------永远爱你们的:Sakura 最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们 ...
- 缓存算法(FIFO 、LRU、LFU三种算法的区别)
FIFO算法 FIFO 算法是一种比较容易实现的算法.它的思想是先进先出(FIFO,队列),这是最简单.最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小.空间满的时 ...
随机推荐
- 7.jenkins 按标签发布
jenkins 如果要按标签发布,需要安装下, Git Parameter Plug-In 的 插件. 之前我们的jar包项目. 我们运行的时候是以下内容. 现在我们对这个jar进行小范围修改. ...
- 201871010106-丁宣元 《面向对象程序设计(java)》第一周学习总结
丁宣元 <面向对象程序设计(java)>第一周学习总结 正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在 ...
- LG5337/BZOJ5508 「TJOI2019」甲苯先生的字符串 线性动态规划+矩阵加速
问题描述 LG5337 BZOJ5508 题解 设\(opt_{i,j}(i \in [1,n],j \in [1,26])\)代表区间\([1,i]\),结尾为\(j\)的写法. 设\(exist_ ...
- Where does Oracle SQL Developer store connections? oracle SQL Developer 连接信息保存的位置,什么地方
oracle SQL Developer 连接信息保存的位置,在什么地方? 在切换登录用户后,oracle SQL Developer 连接信息不见了.只要以前的用户信息还存在,可以在路径 C:\Us ...
- Android 中的AlertDialog使用自定义布局
Android使用指定的View开发弹窗功能 Android开发中进程会使用到我们的AlertDialog,但是比较可惜的是我们的Android原生的AlertDialog的效果又比较的简陋,这个时候 ...
- Android开发笔记:Android开发环境搭建
基于Eclipse开发 1. 安装JDK 首先进入JDK下载页面,选择需要的版本下载安装. JDK 下载地址:https://www.oracle.com/technetwork/java/javas ...
- 第04组 Alpha冲刺(4/4)
队名:斗地组 组长博客:地址 作业博客:Alpha冲刺(4/4) 各组员情况 林涛(组长) 过去两天完成了哪些任务: 1.分配展示任务 2.收集各个组员的进度 3.写博客 展示GitHub当日代码/文 ...
- beego安装错误处理
1. 安装beego时无法安装go依赖包 解决办法: $vim ~/.bashrc export GOPROXY=https://goproxy.io $source ~/.bashrc$go get ...
- dom元素上添加断点(使用dom breakpoint找到修改属性的javascript代码)
使用dom breakpoint能快速找到修改了某一个dom element的JavaScript code位于何处.在Chrome development tool里,选中想要inspect的dom ...
- Spring核心(IoC) 入门解读
什么是IoC容器和Bean? 说到容器,就是用来装东西,那么这里边装的是什么那?是bean对象.那么你会问什么是bean?这就要从很久很久以前说起,当我们创建对象的时候,我们会new一个对象出来,但是 ...