Dijkstra,floyd,spfa三种最短路的区别和使用
这里不列举三种算法的实现细节,只是简单描述下思想,分析下异同
一 Dijkstra
Dijkstra算法可以解决无负权图的最短路径问题,只能应付单源起点的情况,算法要求两个集合,开始所有点在第二个集合,然后将起点加入第一个集合,接着第二个集合剩下的点哪个离起点距离最小,就加入第一个集合,并对其相关的边进行松弛,如此循环直到所有点都进入集合。每个点都加进集合需要循环n次,每个点进入集合又要对不在集合的点距离进行更新,内层又要循环n次。开始将map全部初始化为INF(一个很大的数),这样松弛的时候比较轻松
①复杂度:O(V^2 + E)
一般用邻接矩阵表示图,这种情况下是比较普遍的情况,因为要循环每个点,每个点又要找最小值,复杂度还是挺高的。
②邻接表+优先队列优化后复杂度:O((V + E)lgV)
使用了STL中的优先队列
typedef pair<int,int> PII;
priority_queue<PII,vector<PII>,greater<PII> > q;
...
while(!q.empty()){ // O(V) 加上count<n可以优化一点点
int w=q.top().first, u=q.top().second;
q.pop(); // O(lgV)
if(b[u])continue; b[u]=true;
//++count;
for(int i=head[u];i;i=e[i].next){ // Sum -> O(E)
int v=e[i].to;
if(d[u]+e[i].w<d[v]){
d[v]=d[u]+e[i].w;
q.push(PII(d[v],v)); // O(lgV)
}
}
}
Dijkstra+heap是用小根堆,每次取出d最小的点,来更新距离,那么这个点来说,最小距离就是当前的d。
稠密图中,Dijkstra+heap优化比较快
③记录路径
记录路径是通过一个pre[]数组记录前驱的节点,初始化的时候需要注意,与s直接相连的点i要初始化为pre[i] = s,即使与s直接相连的边不一定是i的最短路径
void dijkstra(int s, int e)
{
int Min, next;
for(int i = ; i <= n; i++)
{
dist[i] = Map[s][i];
vis[i] = false;
pre[i] = dist[i]!=INF&&i!=s ? s : -;//初始化要注意
}
vis[s] = true;
for(int i = ; i <= n; i++)
{
Min = INF;
for(int j = ; j <= n; j++)
{
if(!vis[j] && dist[j] < Min)
{
Min = dist[j];
next = j;
}
}
vis[next] = true;
for(int j = ; j <= n; j++)
{
if(!vis[j] && dist[j] > dist[next] + Map[next][j])
{
dist[j] = dist[next] + Map[next][j];
pre[j] = next;//记录
}
}
}
}
二 Floyd
Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。
基本思路就是假设图有n个点到n个点的距离共n^2段距离(如果是完全图),又分别用n个点松弛它,所以为n^3
Floyd算法的好处是可以计算任意两点间的最短距离,若遇到需要对多个起点终点找最短路径的题目就适合使用Floyd算法。
需要学习的是Floyd记录路径的方法
path[i][j]记录的是i到j的最短路的下一个点,比如i--k--j是i到j的最短路,则path[i][j] = k; path[k][j] = j
需要注意的是path的初始化。
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
pre[i][j] = j; //初始化
for( int k = ; k <= N; k++ )
for( int i = ; i <= N; i++ )
for( int j = ; j <= N; j++ )
{
//////处理最短路图map///////
pre[i][j] = pre[i][k];//记录
}
三 spfa(Shortest Path Faster Algorithm)
spfa是求单源最短路的一种算法,他是再Bellman-Ford算法的基础上加入了队列queue优化,spfa和Dijkstra很像,但spfa可以处理带负权边的图(但是不能有负权环,即围成环的各边权值加起来不能为负)
基本思路是建立一个队列,
①复杂度:??
证明比较复杂,因为每个点不一定只入队列一次,
网上流传的期望时间复杂度为O(me), 其中m为所有顶点进队的平均次数,"可以证明m一般小于等于2n:“算法编程后实际运算情况表明m一般没有超过2n.事实上顶点入队次数m是一个不容易事先分析出来的数,但它确是一个随图的不同而略有不同的常数.所谓常数,就是与e无关,与n也无关,仅与边的权值分布有关.一旦图确定,权值确定,原点确定,m就是一个确定的常数.所以SPFA算法复杂度为O(e).证毕."(SPFA的论文)不过,这个证明是非常不严谨甚至错误的,事实上在bellman算法的论文中已有这方面的内容,所以国际上一般不承认SPFA算法。
SPFA算法有两个优化策略SLF和LLL
SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾;
LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出队进行松弛操作。
SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。
在实际的应用中SPFA的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra
②记录路径
思路与Dijkstra相似,参考Dij的算法。
③(据说稀疏图spfa比较快)
Dijkstra,floyd,spfa三种最短路的区别和使用的更多相关文章
- Java语言----三种循环语句的区别
------- android培训.java培训.期待与您交流! ---------- 第一种:for循环 循环结构for语句的格式: for(初始化表达式;条件表达式;循环后的操作表达式 ...
- png、jpg、gif三种图片格式的区别
png.jpg.gif三种图片格式的区别 2014-06-17 为什么想整理这方面的类容,我觉得就像油画家要了解他的颜料和画布.雕塑家要了解他的石材一样,作为网页设计师也应该对图片格式的特性有一定 ...
- VMware 三种网络模式的区别
VMware 三种网络模式的区别 VMware 三种网络模式的区别 我们首先说一下VMware的几个虚拟设备 VMnet0:用于虚拟桥接网络下的虚拟交换机 VMnet1:用于虚拟Host-Only网络 ...
- JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
JavaScript:学习笔记(7)——VAR.LET.CONST三种变量声明的区别 ES2015(ES6)带来了许多闪亮的新功能,自2017年以来,许多JavaScript开发人员已经熟悉并开始使用 ...
- 转:VMware中三种网络连接的区别
转自:http://www.cnblogs.com/rainman/archive/2013/05/06/3063925.html VMware中三种网络连接的区别 1.概述 2.bridged( ...
- (转)VMware虚拟机三种网络模式的区别及配置方法;
我的一点实际经验理解桥接和NAT 桥接是虚拟机完全作为一个独立的地址接在局域网中,NAT是虚拟机依赖宿主主机地址转换的一种方式 例子我的虚拟机如果用桥接模式,连接外部网站如百度时会提示此pc没有装公司 ...
- poj1847 Tram(Dijkstra || Floyd || SPFA)
题目链接 http://poj.org/problem?id=1847 题意 有n个车站,编号1~n,每个车站有k个出口,车站的出口默认是k个出口中的第一个,如果不想从默认出口出站,则需要手动选择出站 ...
- VMware的三种网络连接方式区别
关于VMware的三种网络连接方式,NAT,Bridged,Host-Only ,在刚接触的时候通常会遇到主机Ping不通虚拟机而虚拟机能Ping得通主机:主机与虚拟机互不相通等等网络问题.本文就这三 ...
- VMware中三种网络连接的区别
1.概述 大家在安装完虚拟机后,默认安装了如下图的两块虚拟网卡——VMnet1和VMnet8,其中VMnet1是host网卡,用于host方式连接网络:VMnet8是NAT网卡,用于NAT方式连接网络 ...
随机推荐
- js 面向对象几种数据模式
一.单例模式: 把描述同一事物的属性和方法放在同一内存空间下,实现了分组的作用,防止同一属性或者方法冲突.我们把这种分组编写代码的模式叫做单例模式即普通的对象. 单例模式是项目开发中最常用的一种开发模 ...
- Struts2中param的作用
1.页面传参与配置传参的区别:如果页面Form表单的参数在Action类中有相应的setter方法,则会优先取页面Form表单传过来的值,如果页面没有该属性同名的参数,则会从配置文件中取同名的参数值作 ...
- VC控件DateTimePicker使用方法
出自http://www.cnblogs.com/52yixin/articles/2111299.html 使用DateTimePicker控件一般是获 取其时间替代手工输入带来的不便,而DateT ...
- Linux常用命令的缩写含义
命令缩写: ls:list(列出目录内容) cd:Change Directory(改变目录) su:switch user 切换用户rpm:redhat package manager 红帽子打包管 ...
- Luogu P3209 [HNOI2010]平面图判定(2-SAT)
P3209 [HNOI2010]平面图判定 题意 题目描述 若能将无向图\(G=(V,E)\)画在平面上使得任意两条无重合顶点的边不相交,则称\(G\)是平面图.判定一个图是否为平面图的问题是图论中的 ...
- API 练习 第一篇
练习API CreateSemaphoreCreateEvent ReleaseSemapWaitForSingleObject CloseHandleInitializeCriticalSec ...
- PHP declare 之 strict_types=1
PHP中申明 declare(strict_types=1)的作用: strict_types=1 及开启严格模式.默认是弱类型校验.具体严格模式和普通模式的区别见下面代码. code1: < ...
- Java虚拟机原理图解-- 1.2、class文件中的常量池
了解JVM虚拟机原理 是每一个Java程序员修炼的必经之路.但是由于JVM虚拟机中有很多的东西讲述的比较宽泛,在当前接触到的关于JVM虚拟机原理的教程或者博客中,绝大部分都是充斥的文字性的描述,很难给 ...
- 【agc019f】AtCoder Grand Contest 019 F - Yes or No
题意 有n个问题答案为YES,m个问题答案为NO. 你只知道剩下的问题的答案分布情况. 问回答完N+M个问题,最优策略下的期望正确数. 解法 首先确定最优策略, 对于\(n<m\)的情况,肯定回 ...
- 线条之美,玩转SVG线条动画
线条之美,玩转SVG线条动画 作者:AlloyTeam www.alloyteam.com/2017/02/the-beauty-of-the-lines-break-lines-svg-animat ...