最短路算法&模板

最短路问题是图论的基础问题。本篇随笔就图论中最短路问题进行剖析,讲解常用的三种最短路算法: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算法堆优化,由于篇幅较长,我放到了另一篇博客中进行讲解,链接:

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的算法,有两种优化方式,由于篇幅较长,放在另一个博客中进行讲解。链接如下:

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;
}
}
}
}

最短路问题的三种算法&模板的更多相关文章

  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 ...

  2. Java利用DES/3DES/AES这三种算法分别实现对称加密

    转载地址:http://blog.csdn.net/smartbetter/article/details/54017759 有两句话是这么说的: 1)算法和数据结构就是编程的一个重要部分,你若失掉了 ...

  3. 内存分配---FF、BF、WF三种算法

    动态分区分配是根据进程的实际需要,动态的为之分配内存空间.而在实现可变分区分配时,将涉及到分区分配中 所用的数据结构.分区分配算法和分区的分配与内存回收的过程. 分区分配中的数据结构:(1)描述空闲块 ...

  4. 图文实例解析,InnoDB 存储引擎中行锁的三种算法

    前文提到,对于 InnoDB 来说,随时都可以加锁(关于加锁的 SQL 语句这里就不说了,忘记的小伙伴可以翻一下上篇文章),但是并非随时都可以解锁.具体来说,InnoDB 采用的是两阶段锁定协议(tw ...

  5. 【2018寒假集训Day 7】【最短路径】三种算法的模板

    Luogu单源最短路径模版题 dijkstra #include<cstdio> #include<vector> using namespace std; const int ...

  6. HDOJ--1869--六度分离(用三种算法写的,希望能比較出来他们之间的差别)

    六度分离 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  7. 常见算法:C语言求最小公倍数和最大公约数三种算法

    最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,当中一个最小的公倍数是他们的最小公倍数,相同地,若干个整数公有的倍数中最小的正整数称为它们的最小公倍数,维基百科:定义点击打开链接 求 ...

  8. C语言求最小公倍数和最大公约数三种算法(经典)

    把以前写的一些经验总结汇个总,方便给未来的学弟学妹们做个参考! --------------------------永远爱你们的:Sakura 最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们 ...

  9. 缓存算法(FIFO 、LRU、LFU三种算法的区别)

    FIFO算法 FIFO 算法是一种比较容易实现的算法.它的思想是先进先出(FIFO,队列),这是最简单.最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小.空间满的时 ...

随机推荐

  1. 201871010113-刘兴瑞《面向对象程序设计(java)》第十四周学习总结

    项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...

  2. python爬虫之爬取网站到数据库

    一.根据已有程序运行得到的结果 完整代码如下: import sqlite3; class DB(object): """数据库访问方法的实现""&q ...

  3. Linux服务器下配置Java环境、JDK

    前言 可以解决问题有/etc/profile与~/.bashrc环境文件区别 文件权限问题,只读readonly Java环境搭建 一.下载JDK包 地址:jdk1.8提取码:gx0b 把文件放到Li ...

  4. Eviews作时间序列分析的一个实例

    时间序列分析是作时间序列数据预测的一个重要部分,由于此次实验室竞赛也用到了时间序列分析,就在此说一下平稳性分析以及非平稳处理的方法:   1.判断平稳性         1.1平稳性的定义       ...

  5. Batch Normalization、Layer Normalization、Instance Normalization、Group Normalization、Switchable Normalization比较

    深度神经网络难训练一个重要的原因就是深度神经网络涉及很多层的叠加,每一层的参数变化都会导致下一层输入数据分布的变化,随着层数的增加,高层输入数据分布变化会非常剧烈,这就使得高层需要不断适应低层的参数更 ...

  6. 基于Docker的Consul服务发现集群搭建

    在去年的.NET Core微服务系列文章中,初步学习了一下Consul服务发现,总结了两篇文章.本次基于Docker部署的方式,以一个Demo示例来搭建一个Consul的示例集群,最后给出一个HA的架 ...

  7. Linux 小工具

    1. 截图工具 shutter 安装 sudo add-apt-repository ppa:shutter/ppa sudo apt-get update sudo apt-get install ...

  8. PHP 的异步并行和协程 C 扩展 Swoole (附链接)

    PHP的异步.并行.高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列, ...

  9. Containers vs Serverless:本质区别是什么?

    在云计算领域,容器和无服务器计算已经占据了发展前列. 作者 | Emra Samdan 翻译 | bocloudresearch 一点历史 在不久以前,应用程序的开发.部署和维护要比现在复杂得多,耗时 ...

  10. Java中的ThreadLocal

    关于 ThreadLocal,我们经常用它来解决多线程并发问题,那它究竟是如何做到的?今天就让我们来好好看一下. 从源码入手 首先,让我们看看 ThreadLocal 类中的介绍: This clas ...