今天做到一道最短路的题,原题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

最新文章

  1. 现有语言不支持XXX方法
  2. JS文档生成工具:JSDoc 介绍
  3. 我对CSS vertical-align的一些理解与认识(一)
  4. bzoj4042
  5. robots.txt协议-互联网robots搜索规范
  6. Java-Android 之动画的实现
  7. 编写可维护的javascript代码--- 2015.11.22(注释)
  8. Silverlight学习(三)
  9. Android 开发佳站【转】
  10. SVN分支的创建,合并,与销毁和相关操作
  11. 康复计划#5 Matrix-Tree定理(生成树计数)的另类证明和简单拓展
  12. 常用http响应报文分析
  13. Java动态代理学习【Spring AOP基础之一】
  14. 关于yaml语言
  15. nginx获取上游真实IP(ngx_http_realip_module)
  16. pytest 11 allure2生成html报告
  17. svn离线安装以及配置,管理python自动化脚本
  18. 马加爵遗书 VS 药家鑫遗书
  19. css---颜色过渡渐变
  20. python使用sqlite

热门文章

  1. linux-yum-downloadonly 下载rpm安装包到本地
  2. windows 通过cmd命令行管理防火墙
  3. js中index()的四种经典用法(转https://blog.csdn.net/superit401/article/details/51726826)
  4. 26. Remove Duplicates from Sorted Array(代码思路新奇)
  5. PostGIS 爆管分析之找出上游阀门(优化版)
  6. oracle三种表连接方式
  7. Linux文档整理之【Jenkins+Docker自动化部署.Net Core】
  8. Ubantu 手动设置DSL连接
  9. python3小demo
  10. Redis启动方式