SPFA算法的SLF优化 ——loj#10081. 「一本通 3.2 练习 7」道路和航线
今天做到一道最短路的题,原题https://loj.ac/problem/10081
题目大意为给一张有n个顶点的图,点与点之间有m1条道路,m2条航线,道路是双向的,且权值非负,而航线是单向的,权值可能为负,保证两点之间如果有航线就不会有道路。现给定起始点s,求s到每个点的最短路径,如果没有则输出“NO PATH”。
我当时看到这题那叫一个高兴啊,以为又是一道水题,因为有负权边,不能用Dijkstra,选择用SPFA。那么有没有负环呢?经过实测数据并没有负环,本以为可以轻松AC了,然而评测结果如下:
最后两个测试点T了。手写队列,读入优化,各种常数优化都用完了,还是超时。现在可以基本确定出数据的人贱贱地卡SPFA了。。。
怎么办呢,又不能用Dijkstra,这时我找到了某某任学长(闻角大仙)。
在某某任学长的帮助下,我了解了一下SPFA的SLF(Small Label First)优化。顾名思义,这种策略就是当要把一个节点入队时,判断它与队头的大小,如果dis[v]<dis[h](v为待入队节点,h为队头),就把它从队头插入,否则从队尾插入。有点贪心的思想,如果这个点比队头还要小的话,就先用它来松弛其它节点。很明显要用双端队列实现了,部分代码如下:
- inline void SPFA(int s)
- {
- register int p,h,v,w;
- fill(dis+,dis+n+,INF);
- dis[s]=;
- vis[s]=true;
- q.push_back(s);
- do
- {
- h=q.front();q.pop_front();
- vis[h]=false;
- for(p=tail[h];p;p=e[p].last)
- {
- v=e[p].v;w=e[p].w;
- if(dis[v]>dis[h]+w)
- {
- dis[v]=dis[h]+w;
- if(!vis[v])
- {
- if(dis[v]<dis[q.front()]&&!q.empty())//这个判断很重要,如果v点比队头更优,就把它从队头入队
- q.push_front(v); //注意双端队列如果在队列为空时从队头入队会出锅的
- else q.push_back(v);
- vis[v]=true;
- }
- }
- }
- }while(!q.empty());
- }
提交后测试情况:
快了好几倍啊!
这里我用的手写的双端队列,因为比用STL更快,附上手写代码(这应该是比较简洁可靠的手写双端队列方式了,一看便知不是我写的):
- struct Deque{
- LL l, r, q[N];
- Deque() {l = ; r = ;}
- bool empty() {return !(l ^ r);}
- void push_back(LL v) {q[r++] = v; r %= N;}
- void push_front(LL v) {q[l = (l - + N) % N] = v;}
- void pop_front() {++l; l %= N;}
- void pop_back() {r = (r - + N) % N;}
- LL front() {return q[l];}
- };
此外SPFA还有LLL(Large Lable Last)优化,这里就不赘述了(其实是笔者不会),有兴趣的朋友可以去了解一下。
希望能帮到大家,请多多指教.
2018-08-17
SPFA算法的SLF优化 ——loj#10081. 「一本通 3.2 练习 7」道路和航线的更多相关文章
- LOJ#10064. 「一本通 3.1 例 1」黑暗城堡
LOJ#10064. 「一本通 3.1 例 1」黑暗城堡 题目描述 你知道黑暗城堡有$N$个房间,$M$条可以制造的双向通道,以及每条通道的长度. 城堡是树形的并且满足下面的条件: 设$D_i$为如果 ...
- LOJ#10117. 「一本通 4.1 练习 2」简单题
LOJ#10117. 「一本通 4.1 练习 2」简单题 题目描述 题目来源:$CQOI 2006$ 有一个$n$个元素的数组,每个元素初始均为$0$.有$m$条指令,要么让其中一段连续序列数字反转— ...
- LOJ #10131 「一本通 4.4 例 2」暗的连锁
LOJ #10131 「一本通 4.4 例 2」暗的连锁 给一棵 \(n\) 个点的树加上 \(m\) 条非树边 , 现在需要断开一条树边和一条非树边使得图不连通 , 求方案数 . $n \le 10 ...
- SPFA算法(SLF优化)2022.7.8更新
SPFA可能会被卡掉,能用dijkstra就别用SPFA,代码较长,但我已尽力做到解释,请耐心看下去,存储为邻接表存储. #include<bits/stdc++.h> #define i ...
- LOJ #10084. 「一本通 3.3 练习 1」最小圈(二分+SPFA判负环)
题意描述: 见原LOJ:https://loj.ac/problem/10084 题解: 假设所求的平均最小值为X,环上各个边的权值分别为A1,A2...Ak,可以得到: X=(A1+A2+A3+.. ...
- LOJ #10132. 「一本通 4.4 例 3」异象石
题目地址 LOJ 题解 神仙思路.思路参考自<算法竞赛进阶指南>. 考虑维护dfs序中相邻两个石头的距离,那么每次?的答案就是sum/2(首尾算相邻) 然后维护一下拿个平衡树/set维护一 ...
- LOJ#10065. 「一本通 3.1 例 2」北极通讯网络
题目链接:https://loj.ac/problem/10065 题目描述 原题来自:Waterloo University 2002 北极的某区域共有 nnn 座村庄,每座村庄的坐标用一对整数 ( ...
- LOJ#10172. 「一本通 5.4 练习 1」涂抹果酱
题目链接:https://loj.ac/problem/10172 题目描述 Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕.蛋糕俯视图是一个 N×MN×MN×M 的矩形,它被划分成 ...
- Loj 10115 「一本通 4.1 例 3」校门外的树 (树状数组)
题目链接:https://loj.ac/problem/10115 题目描述 原题来自:Vijos P1448 校门外有很多树,学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的 ...
随机推荐
- Java设计给小学生的自动出题系统
系统要求: 1.自动出题,涉及加减乘除四则运算 2.运算为两位数之间 3.减法不能出现负数 4.乘法结果不超过100 5.除法必须整除 6.用户决定出题量 7.用户决定几道题一换行 8.题目不允许重复 ...
- HDU 2586——How far away ?
Time limit 1000 ms Memory limit 32768 kB Description There are n houses in the village and some bidi ...
- python-day1(学前了解)
Markdown基本语法 各级标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 加粗 **加粗文本** 斜体 *我斜了* 高亮 ==我高亮了== 上标 2 ...
- 均值滤波器(平滑空间滤波器)基本原理及Python实现
1. 基本原理 使用元素的领域内像素的平均值代替该元素,可明显的降低图像灰度的尖锐变换.它的一种重要应用是模糊处理:得到感兴趣的区域的粗略表示,将次要的/小的元素与背景融合,使得主要的/较大的元素变得 ...
- IDEA配置远程git仓库
一,在项目创建本地仓储 2,选择当前文件夹为本地仓储 3, 将代码添加到本地仓库 4,提交到本地仓库 5,提交到本地仓库 配置远程账号和地址 输入你自己的远程仓库----码云或者github,创建的 ...
- 动态代理之JDK 和 CGLIB
方式一:jdk动态代理 通过proxy类的newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHand ...
- cookie Web Storage API
https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API https://d ...
- Js不用for,forEach,map等循环实现九九乘法表
var str='';function mt(p,n){ if(p<10){ if (n<=p){ str += n+'*'+p+'='+p*n+'\t'; n++; mt(p,n); } ...
- CSS hack(过滤器)
CSS hack概念: 是针对不同浏览器对同一段代码解析不同的处理方案:<解决兼容性问题> 属性设置在不同版本的IE里会出现不兼容问题,css hack解决兼容主流浏览器和IE 常见的过滤 ...
- Linux学习--第十三天--日志、系统运行级别、grub加密
日志 rsyslogd取代了syslogd. /var/log/cron #定时任务相关日志 /var/log/cups #打印信息相关日志 /var/log/dmesg #开机内核自检相关日志,dm ...