今天做到一道最短路的题,原题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」道路和航线的更多相关文章

  1. LOJ#10064. 「一本通 3.1 例 1」黑暗城堡

    LOJ#10064. 「一本通 3.1 例 1」黑暗城堡 题目描述 你知道黑暗城堡有$N$个房间,$M$条可以制造的双向通道,以及每条通道的长度. 城堡是树形的并且满足下面的条件: 设$D_i$为如果 ...

  2. LOJ#10117. 「一本通 4.1 练习 2」简单题

    LOJ#10117. 「一本通 4.1 练习 2」简单题 题目描述 题目来源:$CQOI 2006$ 有一个$n$个元素的数组,每个元素初始均为$0$.有$m$条指令,要么让其中一段连续序列数字反转— ...

  3. LOJ #10131 「一本通 4.4 例 2」暗的连锁

    LOJ #10131 「一本通 4.4 例 2」暗的连锁 给一棵 \(n\) 个点的树加上 \(m\) 条非树边 , 现在需要断开一条树边和一条非树边使得图不连通 , 求方案数 . $n \le 10 ...

  4. SPFA算法(SLF优化)2022.7.8更新

    SPFA可能会被卡掉,能用dijkstra就别用SPFA,代码较长,但我已尽力做到解释,请耐心看下去,存储为邻接表存储. #include<bits/stdc++.h> #define i ...

  5. LOJ #10084. 「一本通 3.3 练习 1」最小圈(二分+SPFA判负环)

    题意描述: 见原LOJ:https://loj.ac/problem/10084 题解: 假设所求的平均最小值为X,环上各个边的权值分别为A1,A2...Ak,可以得到: X=(A1+A2+A3+.. ...

  6. LOJ #10132. 「一本通 4.4 例 3」异象石

    题目地址 LOJ 题解 神仙思路.思路参考自<算法竞赛进阶指南>. 考虑维护dfs序中相邻两个石头的距离,那么每次?的答案就是sum/2(首尾算相邻) 然后维护一下拿个平衡树/set维护一 ...

  7. LOJ#10065. 「一本通 3.1 例 2」北极通讯网络

    题目链接:https://loj.ac/problem/10065 题目描述 原题来自:Waterloo University 2002 北极的某区域共有 nnn 座村庄,每座村庄的坐标用一对整数 ( ...

  8. LOJ#10172. 「一本通 5.4 练习 1」涂抹果酱

    题目链接:https://loj.ac/problem/10172 题目描述 Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕.蛋糕俯视图是一个 N×MN×MN×M 的矩形,它被划分成 ...

  9. Loj 10115 「一本通 4.1 例 3」校门外的树 (树状数组)

    题目链接:https://loj.ac/problem/10115 题目描述 原题来自:Vijos P1448 校门外有很多树,学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的 ...

随机推荐

  1. 2015 四川省赛 C Censor(哈希 | KMP)

    模式串为子串 KMP /* @author : victor */ #include <bits/stdc++.h> using namespace std; typedef long l ...

  2. div css 布局对seo 影响 布局原则

    一.代码精简 使用DIV+CSS布局,页面代码精简,这一点相信对XHTML有所了解的都知道.代码精简所带来的直接好处有两点:一是提高蜘蛛爬行效率,能在最短的时间内爬完整个页面,这样对收录质量有一定好处 ...

  3. 使用layer弹窗和layui表单做新增功能

    注释:代码参考http://blog.51cto.com/825272560/1891158,在其修改之上而来,在此感谢! 1.需求:使用layer在弹窗内完成新增,成功后提示并刷新页面(父页面,li ...

  4. nodejs express 上传文件自定义文件名和上传路径

    1.客户端 <form action="http://localhost:3000/profile" method="post" enctype=&quo ...

  5. 基于centos7,python3.7新建第一个Django项目

    为了能更好的了解到整个网站的服务情况,需要了解前端,后端之间的联系,这时候就得需要用到Django框架,基于Django自身带的模板,它可以更好的接收用户发出请求,接下来讲解一下新建第一个Django ...

  6. linux下 设置php的环境变量 php: command not found

    在自己的根目录进行运行phpinfo();     查看php的根目录. 假如自己查询的目录是/www/wdlinux/apache_php-5.6.21/bin, 查询完成后,先进入linux目录查 ...

  7. .NET Framework 2.0/3.0/3.5 以 v90 平台工具集为目标。请确保在计算机上安装了 Visual Studio 2008

    今天在Visual Studio2010下面开发C++应用的时候发现“.NET Framework 2.0/3.0/3.5 以 v90 平台工具集为目标.请确保在计算机上安装了 Visual Stud ...

  8. RHEL6 中/etc/fstab文件解析

    1.系统环境 [root@natsha ~]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 6.5 (Santiag ...

  9. DCGAN生成式对抗网络--keras实现

    本文针对cifar10 图集进行了DCGAN的复现. 其中库中的SpectralNormalizationKeras需添加至python环境中 该篇代码如下: from keras import ba ...

  10. bat 感想

    用bat做了个跨版本更新包的生成脚本,由于之前都是写一些很简单bat,或者python里使用windows命令,所以纯用bat做这个东西,还是有点复杂的. 过程中遇到很多问题,主要是参数太多,变量的使 ...