7.11 Update

我做题的时候发现这样写会RE

因为在使用双端队列优化SPFA的时候 在将一个点加入队列的时候,如果队列已经空了 那么一旦出现dis[Q.front()]就会RE 可以这样修改

if(!Q.empty()) {
if(dis[v[k]] < dis[Q.front()]) Q.push_front(v[k]);
else Q.push_back(v[k]);
}
else Q.push_front(v[k]);

这样就不会RE了

期望时间复杂度:O(k*e或me)//k是增长很快的函数ackermann的反函数,2^65536次方也就5以下,但是可以被恶意数据卡掉,起复杂度就位(n*n ) //其中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算法

上面这两段话呢,来自百度。

关于SPFA的时间复杂度,地球人应该都知道非常玄学的,近似可以看作O(看脸),

对于上面所说的最坏情况,我还记得有一次考试的题目中有一道最短路问题。

那道题的最后一组数据是用来卡SPFA的,(吓,出题人好毒瘤

这里我们不介绍LLL优化,

Only SLF优化


在每一次松弛操作的时候都已进入队列的操作

可是朴素的SPFA中将元素放到队列中时无序的,

如果改用一种很吊的队列的话,将其中的元素变得有点儿顺序

就可以起到优化的作用

这便是SLF优化

我们使用c++STL中的deque来实现上述操作

建议Pascal选手尽快转C++吧

下面就是代码(可能会很丑哦)

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <deque>
#include <algorithm> const int maxnode = 1e4+;
const int maxedge = 5e5+; #define INF 2147483647 using namespace std; deque<int> Q; int first[maxnode], next[maxedge], n, m, s;
int u[maxedge], v[maxedge], w[maxedge], dis[maxnode]; bool vis[maxnode]; inline int read() {
char c = getchar();
int x = , f = ;
while (c < '' || c > '') {
if(c == '-') f = -;
c = getchar();
}
while (c <= '' && c >= '') {
x = x* + c-'';
c = getchar();
}
return x * f;
} inline void addedge(int from, int i) {
next[i] = first[from];
first[from] = i;
} inline void SPFA(int sta) {
Q.push_back(sta), vis[sta] = true;
while (!Q.empty()) {
int x = Q.front();
int k = first[x];
Q.pop_front();
while (k != -) {
if (dis[v[k]] >= dis[u[k]] + w[k]) {
dis[v[k]] = dis[u[k]] + w[k];
if (!vis[v[k]]) {
vis[v[k]] = ;
if (dis[v[k]] < dis[Q.front()]) Q.push_front(v[k]);
else Q.push_back(v[k]);
}
}
k = next[k];
}
vis[x] = ;
}
} int main() {
n = read(), m = read(), s = read();
for (int i=; i<=n; i++) dis[i] = INF;
dis[s] = ;
memset(first, -, sizeof(first));
for (int i=; i<=m; i++) {
u[i] = read(), v[i] = read(), w[i] = read();
addedge (u[i], i);
}
SPFA(s);
for (int i=; i<=n; i++) printf("%d ", dis[i]);
}

关于SPFA的双端队列优化的更多相关文章

  1. poj 3259 Wormholes : spfa 双端队列优化 判负环 O(k*E)

    /** problem: http://poj.org/problem?id=3259 spfa判负环: 当有个点被松弛了n次,则这个点必定为负环中的一个点(n为点的个数) spfa双端队列优化: 维 ...

  2. Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化

    设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就 ...

  3. POJ3662 SPFA//二分 + 双端队列最短路

    https://cn.vjudge.net/problem/12427/origin 题意:求1到N第K + 1大条边权最小的路径 首先想到dp递推,dp[x][y]表示到x这个点经过y条免费边的最小 ...

  4. P - The Shortest Path in Nya Graph-hdu4725(双端队列+拆点)

    题意:有N个点和N层..一层有X个点(0<=X<=N).两邻两层间有一条路花费C.还有M条小路在两个点之间.问从第一个点走到第N个点最短路是多少... 可以考虑在每一层增加一个点,这个点到 ...

  5. STL---deque(双端队列)

    Deque是一种优化了的.对序列两端元素进行添加和删除操作的基本序列容器.它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结 ...

  6. 2601 电路维修 (双端队列bfs\优先队列bfs(最短路))

    描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板 ...

  7. 自己动手实现java数据结构(四)双端队列

    1.双端队列介绍 在介绍双端队列之前,我们需要先介绍队列的概念.和栈相对应,在许多算法设计中,需要一种"先进先出(First Input First Output)"的数据结构,因 ...

  8. CH 2601 - 电路维修 - [双端队列BFS]

    题目链接:传送门 描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致 ...

  9. 【C++】STL常用容器总结之五:双端队列deque

    6.双端队列deque 所谓的deque是”double ended queue”的缩写,双端队列不论在尾部或头部插入元素,都十分迅速.而在中间插入元素则会比较费时,因为必须移动中间其他的元素.双端队 ...

随机推荐

  1. 蓝书2.4 AC自动机

    T1 玄武密码 bzoj 4327 题目大意: 一些字符串 求这些字符串的前缀在母串上的最大匹配长度是多少 思路: 对于所有串建立AC自动机 拿母串在自动机上匹配 对所有点打标记 以及对他们的fail ...

  2. python cmd 启动python项目报错:no module named “xxx”

    场景:使用pycharm编辑器启动pyhon项目时可以启动,但使用cmd启动时,会报:no module named “xxx”的错误,此时,有两种情况: 1.no module named “xxx ...

  3. 杂项-Java:Ehcache

    ylbtech-杂项-Java:Ehcache EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. 1.返回顶部 1. 基 ...

  4. vue 目录结构介绍

    1 初始目录如下: 2 目录结构介绍 bulid:最终帆布的代码存放位置 config:配置目录,包括端口号等 node_modules:npm加载的项目依赖模块 src:z这里是我们要开发的目录,基 ...

  5. Tomcat组件

    Tomcat组件 tomcat常用组件 Tomcat的组织结构 Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的给件是CATALINA SERVLET容器,其他的组件按照一定 ...

  6. hdu4292 Food 最大流模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292 题意:水和饮料,建图跑最大流模板. 我用的是学长的模板,最然我还没有仔细理解,不过这都不重要直接 ...

  7. js最全的十种跨域解决方案

    在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同 源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问 ...

  8. wamp集成环境下帝国备份出错

    我在本地wamp环境下面使用帝国备份王时,报错信息如下: Parse error: syntaxerror, unexpected $end in D:wampwwwhuifuclassfunctio ...

  9. vue.js学习文档

    1.实例化vue对象 new Vue(){ } 2.对象属性 el: 控制的属性 data: 数据存储位置 methods: 方法存储位置 template: 模板样式 computed: 计算属性 ...

  10. 转】 mysql5.6.12 for Linux安装

    原博文出自于: http://blog.csdn.net/book_mmicky/article/details/25714049 感谢! 1:上www.mysql.org下载64位版本mysql5. ...