【最短路径】 SPFA算法优化
首先先明确一个问题,SPFA是什么?(不会看什么看,一边学去,传送门),SPFA是bellman-ford的队列优化版本,只有在国内才流行SPFA这个名字,大多数人就只知道SPFA就是一个顶尖的高效算法,却不知道还能继续优化,这个优化虽然也没有你想的那么麻烦,只不过多了几个判断语句罢了,5分钟就能学会,但是这也得运用到分类讨论,其实SPFA有三种优化方法,效果并不是很明显。
这三个测试点通过情况所对应的分别是SPFA的三种优化方法,这个时间也是因题而异,像这道题,效果并不好,但是看别人写的博客,他们提交了一道数据对于优化后的SPFA比较有利,测试时间差距能看出来,但是效果也就是减少十几毫秒而已,但是也是有的,万一题目会卡这十几毫秒呢?
1. SLF优化
还记得吗?在我们学SPFA的时候,要把每一个入队的点插入到队尾,可是有些时候这个点作为队尾没有作为队头效率高,因为这个点有时放在队首就能直接用,那么什么样的点作为队首更好呢?当然是dis值越小越可能刷新其它dis值,所以对比当前元素与对首元素的dis值,如果当前元素的dis值更小,那么把当前元素插入到队首,否则插入到队尾。如果你不是很了解队列,或者还是现学的,一定会纳闷,不就能q.push( );吗?哪来的队首呢?此时queue<int>q;应该改为deque<int>q;双端队列,就有q.push_front( );和q.push_back( );了。
代码如下(红色处为优化对应的新增代码):
- void SPFA()
- {
- memset(dis,inf,sizeof(dis));
- deque<int>q;
- q.push_back();dis[]=;vis[]=;
- while(q.size())
- {
- x=q.front();q.pop_front();vis[x]=;
- for(int i=head[x];i;i=map[i].next)
- {
- s=map[i].to;
- if(dis[s]>dis[x]+map[i].value)
- {
- dis[s]=dis[x]+map[i].value;
- if(vis[s]==)
- {
- if(dis[s]<dis[q.front()]) q.push_front(s);
- else q.push_back(s);
- vis[s]=;
- }
- }
- }
- }
- }
2. LLL优化
如果懂了上一个SLF优化,那么这个LLL优化就很好理解了,SLF表示小的优先,LLL表示大的最后,那么什么样的的dis值是大的呢?难道还和队首元素比较吗?当然不是,是于队列的平均数来比较,如果大于这个平均数就放到最后。
代码如下(红色处为优化对应的新增代码):
- void SPFA()
- {
- memset(dis,inf,sizeof(dis));
- queue<int>q;
- q.push();dis[]=;vis[]=;
- while(q.size())
- {
- p=q.front();q.pop();
- if(dis[p]*cnt_2>sum)
- {
- q.push(p);
- continue;
- }
- sum-=dis[p];cnt_2--;
- vis[p]=;
- for(int i=head[p];i;i=map[i].next)
- {
- s=map[i].to;
- if(dis[s]>dis[p]+map[i].value)
- {
- dis[s]=dis[p]+map[i].value;
- if(vis[s]==)
- {
- vis[s]==;
- q.push(s);
- cnt_2++;
- sum+=dis[s];
- }
- }
- }
- }
- }
2. SLF+LLL优化
这个就很简单直接了,把两个新增代码搓一块了就行。
代码如下(红色处为优化对应的新增代码):
- void SPFA()
- {
- memset(dis,inf,sizeof(dis));
- deque<int>q;
- q.push_back();dis[]=;vis[]=;
- while(q.size())
- {
- p=q.front();q.pop_front();
- if(dis[p]*cnt_2>sum)
- {
- q.push_back(p);
- continue;
- }
- sum-=dis[p];cnt_2--;
- vis[p]=;;
- for(int i=head[p];i;i=map[i].next)
- {
- s=map[i].to;
- if(dis[s]>dis[p]+map[i].value)
- {
- dis[s]=dis[p]+map[i].value;
- if(vis[s]==)
- {
- vis[s]==;
- if(dis[s]<dis[q.front()]) q.push_front(s);
- else q.push_back(s);
- cnt_2++;
- sum+=dis[s];
- }
- }
- }
- }
- }
怎么样,你学会了吗?
【最短路径】 SPFA算法优化的更多相关文章
- 最短路径--SPFA 算法
适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径一 ...
- 最短路径——SPFA算法
一.前提引入 我们学过了Bellman-Ford算法,现在又要提出这个SPFA算法,为什么呢? 考虑一个随机图(点和边随机生成),除了已确定最短路的顶点与尚未确定最短路的顶点之间的边,其它的边所做的都 ...
- 最短路径----SPFA算法
求最短路径的算法有许多种,除了排序外,恐怕是ACM界中解决同一类问题算法最多的了.最熟悉的无疑是Dijkstra,接着是Bellman-Ford,它们都可以求出由一个源点向其他各点的最短路径:如果我们 ...
- 图的最短路径-----------SPFA算法详解(TjuOj2831_Wormholes)
这次整理了一下SPFA算法,首先相比Dijkstra算法,SPFA可以处理带有负权变的图.(个人认为原因是SPFA在进行松弛操作时可以对某一条边重复进行松弛,如果存在负权边,在多次松弛某边时可以更新该 ...
- 洛谷P3371单源最短路径SPFA算法
SPFA同样是一种基于贪心的算法,看过之前一篇blog的读者应该可以发现,SPFA和堆优化版的Dijkstra如此的相似,没错,但SPFA有一优点是Dijkstra没有的,就是它可以处理负边的情况. ...
- SPFA算法优化
前言 \(SPFA\) 通常在稀疏图中运行效率高于 \(Dijkstra\) ,但是也容易被卡. 普通的 \(SPFA\) 时间复杂度为 \(O(km)\) ,其中 \(k\) 是一条边松弛其端点点的 ...
- 最短路径SPFA算法(邻接表存法)
queue <int> Q; void SPFA (int s) { int i, v; for(int i=0; i<=n; i++) dist[i]=INF; //初始化每点i到 ...
- 【最短路径】 SPFA算法
上一期介绍到了SPFA算法,只是一笔带过,这一期让我们详细的介绍一下SPFA. 1 SPFA原理介绍 SPFA算法和dijkstra算法特别像,总感觉自己讲的不行,同学说我的博客很辣鸡,推荐一个视频讲 ...
- luogu P3371 & P4779 单源最短路径spfa & 最大堆优化Dijkstra算法
P3371 [模板]单源最短路径(弱化版) 题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出 ...
随机推荐
- ZOJ 3774 二次剩余
LINK 题意:简单粗暴,求菲波那契数列每个数的m次的前n项和模1e9+7 思路:斐波那契通项式, 注意到有很多根号5,求二次剩余为5模1e9+7的解,显然我们可以直接找一个(383008016),然 ...
- phpcms取内容发布管理中的来源
调取内容发布管理中的来源,如果直接写{$val['copyfrom']}调取出来的内容为 内容|0 ,要先根据“|”进行拆分,然后再写. 示例: <!--新闻开始--> {pc:co ...
- Fiddler 抓包工具总结(转)
阅读目录 1. Fiddler 抓包简介 1). 字段说明 2). Statistics 请求的性能数据分析 3). Inspectors 查看数据内容 4). AutoResponder 允许拦截制 ...
- python基础===python自带idle的快捷键
Ctrl + [ Ctrl + ] 缩进代码Alt+3 Alt+4 注释.取消注释代码行Alt+5 Alt+6 切换缩进方式 空格<=>TabAlt+/ 单词完成,只要文中出现过,就可 ...
- 读书笔记 effective c++ Item 4 确保对象被使用前进行初始化
C++在对象的初始化上是变化无常的,例如看下面的例子: int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证.看下面的例子: class Point { int x,y; ...
- js固定小数位数 .toFixed()
toFixed(num)法可把 Number 四舍五入为指定小数位数的数字. num为需要固定的位数 var num=2;console.log(num.toFixed(2));//2.00;var ...
- centos7安装lamp
一.准备工作 1. 下载并安装CentOS7.2,配置好网络环境,确保centos能上网,可以获取到yum源. centos7.2的网络配置: vim /etc/sysconfig/network ...
- HTTPS握手过程
HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密.具体是如何进行加密,解密,验证的,且看下图,下面的称为一次握手. 1. 客户端发起HT ...
- hive学习(六) 参数和动态分区
1.hive 参数.变量 1.1hive的命名空间: hive当中的参数.变量,都是以命名空间开头
- LeetCode679. 24 Game
You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated ...