【为什么要优化】

关于SPFA,他死了(懂的都懂)

 

进入正题。。。

一般来说,我们有三种优化方法。

SLF优化:

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

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

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

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

 deque<int> q;

 inline void spfa(int x)
{
memset(d,0x3f,sizeof(d));
memset(v,,sizeof(v));
d[x]=;v[x]=;
q.push_back(x);
while(q.size())
{
int index=q.front();q.pop_front();
v[index]=;
for(int i=head[index];i;i=g[i].next){
int y=g[i].ver,z=g[i].edge;
if(d[y]>d[index]+z){
d[y]=d[index]+z;
if(!v[y]){
if(!q.empty()&&d[y]>=d[q.front()]) q.push_back(y);
else q.push_front(y);
v[y]=;
}
}
}
}
}

LLL优化:

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

一般用SLF+LLL可以优化50%左右,但是在竞赛中并不常用LLL优化。(所以我就懒得写了,这是从这个大佬那里嫖来的)

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

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

 void spfa(){
int u,v,num=;
long long x=;
list<int> q;
for(int i=;i<=n;i++){path[i]=MAX;vis[i]=false;}
path[s]=;
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=;i<=n;i++)printf("%d ",path[i]);
printf("\n");
}

DFS优化:

这种优化顾名思义,就是用dfs的思想代替bfs的思想来优化Bellman-Ford。

常常用于判断正/负环,时间复杂度可以达到O(m)(m是边)。思路是,我们每一次dfs的时候如果走回之前dfs过的点,那就是有环,除了这个dfs的标记,我们还可以打另一个vis数组记录更新过权值的节点,以后就不必重复更新,大大降低复杂度。

不过如果无环的话,那还是上面那两种优化稍微适用一点。代码比较短,但是不好扩展。

 inline bool spfa(int x)
{
dfs[x]=;
for(int i=head[x];i;i=g[i].next)
{
int y=g[i].ver,z=g[i].edge;
if(!v[y]||d[y]<d[x]+z){
if(dfs[y]) return ;
v[y]=;
d[y]=d[x]+z;
if(!spfa(y)) return ;
}
}
dfs[x]=;
return ;
}

最新文章

  1. Windows内网渗透提权的几个实用命令
  2. BZOJ-1087 互不侵犯King 状压DP+DFS预处理
  3. 使自定义事件支持多绑定 js
  4. 【BZOJ】【4004】【JLOI2015】装备购买
  5. Java执行groovy脚本
  6. 【转】小解DCT与DFT
  7. QTP小应用一则
  8. 用持续集成工具Travis进行构建和部署
  9. 中兴电信光纤猫F450获取管理员密码方法
  10. JavaScript学习笔记(七)——函数的定义与调用
  11. 绘制静态地图API-高德地图
  12. 将函数声明为Static的作用
  13. HDOJ 6508 Problem I. Spell Boost (01背包/DP)
  14. Bellman-Ford算法(在边权可正可负时求最短路)
  15. 前端(五)之display 总结与浮动
  16. 关于linux特殊含义的转义符\033
  17. STL - 容器 - Set
  18. Android适配--百分比的适配
  19. Python 处理脚本的命令行参数-getopt
  20. Pandas排序

热门文章

  1. NOIp 2009:靶形数独
  2. UIPath工具取得多个文件的方法
  3. 关于verilog实例化的介绍
  4. 【leetcode算法-简单】58. 最后一个单词的长度
  5. 将 PDF 论文的公式截图后转成 Word 可编辑公式(23)
  6. python学习--13 基本数据类型 2
  7. 【判环】Perpetuum Mobile
  8. 项目element-ui checkbox里面获取选中项 实现批量删除 修改
  9. asp.net core-4.命令行配置
  10. java中单双引号的区别