先举出个例题:洛谷P3371 【模板】单源最短路径

一眼扫去:最短路径。

spfa不接受反驳。。。

附上代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define MAXN 10010
#define MAX 999999999
using namespace std;
int n,m,s,c=1;
int head[MAXN],path[MAXN];
bool vis[MAXN];
struct node{int next,to,w;
}a[MAXN*100];
inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;
}
inline int relax(int u,int v,int w){if(path[v]>path[u]+w){path[v]=path[u]+w;return 1;}return 0;
}
inline void add(int u,int v,int w){a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
}
void spfa(){int u,v;queue<int> q;for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}path[s]=0;vis[s]=true;q.push(s);while(!q.empty()){u=q.front();q.pop();vis[u]=false;for(int i=head[u];i;i=a[i].next){v=a[i].to;if(relax(u,v,a[i].w)&&!vis[v]){vis[v]=true;q.push(v);}}}for(int i=1;i<=n;i++)printf("%d ",path[i]==MAX?2147483647:path[i]);
}
int main(){int u,v,w;n=read();m=read();s=read();for(int i=1;i<=m;i++){u=read();v=read();w=read();add(u,v,w);}spfa();return 0;
}

然而遇到某些坑爹的题,比如USACO上的某些题,硬生生卡spfa啊!怎么办?

没事,我们有优化——SLF与LLL!


SLF优化:

SLF优化,即 Small Label First  策略,使用 双端队列 进行优化。

一般可以优化15%~20%,在竞赛中比较常用。

设从 u 扩展出了 v ,队列中队首元素为 k ,若 dis[ v ] < dis[ k ] ,则将 v 插入队首,否则插入队尾。

注:队列为空时直接插入队尾。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<deque>
#define MAXN 10010
#define MAXM 500010
#define MAX 2147483647
using namespace std;
int n,m,s,t,c=1;
int head[MAXN],path[MAXN];
bool vis[MAXN];
struct node{int next,to,w;
}a[MAXM<<1];
inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;
}
inline int relax(int u,int v,int w){if(path[v]>path[u]+w){path[v]=path[u]+w;return 1;}return 0;
}
inline void add(int u,int v,int w){a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
}
void spfa(){int u,v;deque<int> q;for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}path[s]=0;vis[s]=true;q.push_back(s);while(!q.empty()){u=q.front();q.pop_front();vis[u]=false;for(int i=head[u];i;i=a[i].next){v=a[i].to;if(relax(u,v,a[i].w)&&!vis[v]){vis[v]=true;if(!q.empty()&&path[v]<path[q.front()])q.push_front(v);else q.push_back(v);}}}for(int i=1;i<=n;i++)printf("%d ",path[i]);printf("\n");
}
int main(){int u,v,w;n=read();m=read();s=read();for(int i=1;i<=m;i++){u=read();v=read();w=read();add(u,v,w);}spfa();return 0;
}


LLL优化:

LLL优化,即 Large Label Last  策略,使用 双端队列 进行优化。

一般用SLF+LLL可以优化50%左右,但是在竞赛中并不常用LLL优化。

设队首元素为 k ,每次松弛时进行判断,队列中所有 dis 值的平均值为 x 。

若 dist[ k ] > x ,则将 k 插入到队尾,查找下一元素,直到找到某一个 k 使得 dis[ k ] <= x ,则将 k 出队进行松弛操作。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<list>
#define MAXN 10010
#define MAXM 500010
#define MAX 2147483647
using namespace std;
int n,m,s,t,c=1;
int head[MAXN],path[MAXN];
bool vis[MAXN];
struct node{int next,to,w;
}a[MAXM<<1];
inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;
}
inline int relax(int u,int v,int w){if(path[v]>path[u]+w){path[v]=path[u]+w;return 1;}return 0;
}
inline void add(int u,int v,int w){a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
}
void spfa(){int u,v,num=0;long long x=0;list<int> q;for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}path[s]=0;vis[s]=true;q.push_back(s);num++;while(!q.empty()){u=q.front();q.pop_front();num--;x-=path[u];while(num&&path[u]>x/num){q.push_back(u);u=q.front();q.pop_front();}vis[u]=false;for(int i=head[u];i;i=a[i].next){v=a[i].to;if(relax(u,v,a[i].w)&&!vis[v]){vis[v]=true;if(!q.empty()&&path[v]<path[q.front()])q.push_front(v);else q.push_back(v);num++;x+=path[v];}}}for(int i=1;i<=n;i++)printf("%d ",path[i]);printf("\n");
}
int main(){int u,v,w;n=read();m=read();s=read();for(int i=1;i<=m;i++){u=read();v=read();w=read();add(u,v,w);}spfa();return 0;
}


后记:

附上洛谷上的三次提交:

朴素spfa:Accepted  100

336ms /  7.92MB 
代码:1.19KB C++

spfa+SLF: Accepted  100

316ms /  7.89MB 
代码:1.33KB C++

spfa+SLF+LLL: Accepted  100

316ms /  8.08MB 
代码:1.45KB C++

显然,SLF这个优化已经足够了。

再说,就算卡spfa+优化,不就5~10分嘛。。。

$Update 2018.7.29:$:

$NOI2018Day1T1$竟然真的卡了$SPFA$!!!

并且卡了$40$分!!!

出题人你说你卡个$10$分、$20$分也就算了,居然卡了$40$分!!!

大毒瘤。。。

所以对于正权图还是乖乖写堆优化$Dijkstra$吧。。。

附上讲解:

Dijkstra的堆优化

转载于:https://www.cnblogs.com/Yangrui-Blog/p/8997721.html

SPFA的两个优化:SLF与LLL相关推荐

  1. SPFA的SLF与LLL优化

    SPFA算法的优化有两个:SLF与LLL,这两个优化都是利用deque进行的. 1.SLF(Small Label First):为了方便,把新加入的顶点记为v,队首记为u.每次进队时如果dist[v ...

  2. SPFA算法的四种优化(SLF,LLL,SLF+LLL,DFS)

    文章目录 1 基本介绍 2 基础SPFA算法 3 SLF优化 4 LLL优化 5 SLF+LLL优化 6 DFS优化 1 基本介绍 若读者还不太了解SPFA算法,指路一篇博客:https://blog ...

  3. 模式识别新研究:微软OCR两层优化提升自然场景下的文字识别精度

    模式识别新研究:微软OCR两层优化提升自然场景下的文字识别精度 发表于2015-03-30 23:46| 6209次阅读| 来源CSDN| 8 条评论| 作者霍强 模式识别微软亚洲研究院微软OCR文字 ...

  4. 冒泡排序和其两种优化

    第一篇博客 会的算法的也不多 就用c++写个冒泡排序 #include <iostream> #include <iomanip> #include <cstring&g ...

  5. Keras实现两个优化器:Lookahead和LazyOptimizer

    Keras实现两个优化器:Lookahead和LazyOptimizer By 苏剑林 | 2019-07-30 | 2232位读者 | 最近用Keras实现了两个优化器,也算是有点实现技巧,遂放在一 ...

  6. oracle 两种优化器,Oracle的优化器有两种优化方式(一)

    Oracle的优化器有两种优化方式(整理), 2010-04-13 RBO方式:基于规则的优化方式(Rule-Based Optimization,简称为RBO)  优化器在分析SQL语句时,所遵循的 ...

  7. 综合能源系统优化 数据来源《考虑需求响应的社区综合能源系统两阶段优化调度_刘蓉晖》

    综合能源系统优化 数据来源<考虑需求响应的社区综合能源系统两阶段优化调度_刘蓉晖> %% 风电+储能+电网交易+燃气轮机+燃气锅炉+电制冷机+(%燃料电池FC+溴化锂制冷机LBR+余热锅炉 ...

  8. 狂雨1.2.2小说CMS系统源码 附两套优化模板 一套采集规则

    介绍: 狂雨1.2.2小说CMS系统源码带两套优化模板和一套采集规则,带安装教程 网盘下载地址: http://kekewl.cc/Zy4inCgIEnL 图片:

  9. MATLB|电动汽车两阶段优化调度策略(Matlab代码实现)

    目录 1 概述 2 数学模型 3 运行结果 4 Matlab代码实现 5 结论 6 全文阅读 1 概述 在当前阶段,电动汽车通常被视为即插即充的常规负荷,这浪费了其可观的储荷能力".研究表明 ...

最新文章

  1. 车联网,挖掘数据价值
  2. linux哪个命令不可以查看文件内容,linux命令--查看文件内容
  3. javascript中获取dom元素高度和宽度
  4. MVC POST请求后执行javascript代码
  5. Robust Point Cloud Registration Framework Based on Deep Graph Matching (RGM) 简略分析
  6. Thinking in C++ Notes 常量
  7. java 类对象_Java中的对象和类是什么?
  8. 孙鑫MFC笔记之十三--多线程编程
  9. pycharm怎样运行python_python – 如何使用PyCharm运行doctests?
  10. Android 7.0(API 24)以上调用系统安装包问题
  11. .fnt 字体不能正常显示
  12. FPN网络详解——feature pyramid network
  13. C语言基础练习100--008(输出国际象棋棋盘)
  14. 2019新征程 | SMIA新一批会员公示
  15. C++版本OpenCv教程(十一)多通道分离与合并
  16. 这所“南方小镇”藏着雅居乐陈卓林描绘的“第二人生”
  17. Unit3D打包android时出错 CommandInvokationFailure: Unable to list target platforms. Please make sure the a
  18. Java SE Development Kit (JDK) 安装
  19. 互联网行业职位介绍——PM,RD,FE,UE,UI,QA,OP,DBA,BRD,MRD, PRD,FSD等
  20. vue工程展示数字动画组件vue animate-number的使用与填坑

热门文章

  1. Cocos2D v2.0至v3.x简洁转换指南(一)
  2. Ext.MessageBox.Show使用Progress
  3. kafka的offset笔记
  4. intellij自动生成构造函数
  5. 三种复方门冬维甘滴眼液的抗菌能力比较
  6. Ubuntu20.04开机界面(boot animation)改成Windows95
  7. UT890D的二极管档的使用
  8. 李航-HMM-直接计算法
  9. 机器学习(五)——SVM(3)
  10. linux cvs服务,Linux环境下轻松搭建CVS服务器