与其说是 SPFA 算法的优化,倒不如说是 Bellman-Ford 算法的优化。

栈优化

将原本的 bfs 改为 dfs,在寻找负环时可能有着更高效的效率,但是最坏复杂度为指数级别。

void dfs_spfa(int u) {
if (fg) return;
vis[u] = true;
for(pil it : son[u]) {
int v = it.first;
ll w = it.second;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (vis[v] == true) {//如果这个点被访问过,就说明这是负环
fg = true;//打标记
return;
}
else dfs_spfa(v);
}
}
vis[u] = false;
}

SLF 优化

将一般的队列换成双端队列,判断与队首元素的 dis 的大小,小的就放队首,大的就放队尾。

void spfa(int s) {
for(int i = 1; i <= n; ++ i) {
dis[i] = inf;
}
dis[s] = 0;
q.push_back(s);
f[s] = 1;
while (!q.empty()) {
int u = q.front();
q.pop_front();
f[u] = 0;
for (pii it : son[u]) {
int v = it.first;
int w = it.second;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (! f[v]) {
if (! q.empty() && dis[v] < dis[q.front()]) {
q.push_front(v);
}
else q.push_back(v);
f[v] = 1;
}
}
}
}
}

D´Esopo-Pape 优化

将队列换成双端队列,判断一个点是否入过队列,没入过就放到队尾,如果就放到队首。

void spfa(int s) {
for(int i = 1; i <= n; ++ i) {
dis[i] = inf;
}
dis[s] = 0;
q.push_back(s);
f[s] = 1;
vis[s] = 1; // 是否入过队
while (!q.empty()) {
int u = q.front();
q.pop_front();
f[u] = 0;
for (pii it : son[u]) {
int v = it.first;
int w = it.second;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (! f[v]) {
if (vis[v]) {
q.push_front(v);
}
else {
q.push_back(v);
vis[v] = 1;
}
f[v] = 1;
}
}
}
}
}

LLL 优化

将普通队列换成双端队列,每次将入队结点距离和队内距离平均值比较,如果更大则插入至队尾,否则插入队首。

void spfa() {
ll sum = 0;
for (int i = 1; i <= n; ++ i) {
dis[i] = inf;
}
dis[s] = 0;
q.push_back(s);
g[s] = 1;
sum += dis[s];
while (!q.empty()) {
int u = q.front();
q.pop_front();
vis[u] = false;
sum -= dis[s];
for (pli it : son[u]) {
if (dis[it.second] > dis[u] + it.first) {
dis[it.second] = dis[u] + it.first;
if (! vis[it.second]) {
if (q.empty() || dis[it.second] > sum / ((int)q.size())) {
q.push_back(it.second);
}
else {
q.push_front(it.second);
g[it.second] = 1;
}
vis[it.second] = true;
}
}
}
}
}

「学习笔记」SPFA 算法的优化的更多相关文章

  1. 「学习笔记」FFT 之优化——NTT

    目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...

  2. 「学习笔记」字符串基础:Hash,KMP与Trie

    「学习笔记」字符串基础:Hash,KMP与Trie 点击查看目录 目录 「学习笔记」字符串基础:Hash,KMP与Trie Hash 算法 代码 KMP 算法 前置知识:\(\text{Border} ...

  3. 「学习笔记」Min25筛

    「学习笔记」Min25筛 前言 周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}​\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK ...

  4. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  5. 「学习笔记」Treap

    「学习笔记」Treap 前言 什么是 Treap ? 二叉搜索树 (Binary Search Tree/Binary Sort Tree/BST) 基础定义 查找元素 插入元素 删除元素 查找后继 ...

  6. 「学习笔记」平衡树基础:Splay 和 Treap

    「学习笔记」平衡树基础:Splay 和 Treap 点击查看目录 目录 「学习笔记」平衡树基础:Splay 和 Treap 知识点 平衡树概述 Splay 旋转操作 Splay 操作 插入 \(x\) ...

  7. 「学习笔记」wqs二分/dp凸优化

    [学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...

  8. 「学习笔记」斜率优化dp

    目录 算法 例题 任务安排 题意 思路 代码 [SDOI2012]任务安排 题意 思路 代码 任务安排 再改 题意 思路 练习题 [HNOI2008]玩具装箱 思路 代码 [APIO2010]特别行动 ...

  9. 「学习笔记」单调队列优化dp

    目录 算法 例题 最大子段和 题意 思路 代码 修剪草坪 题意 思路 代码 瑰丽华尔兹 题意 思路 代码 股票交易 题意 思路 代码 算法 使用单调队列优化dp 废话 对与一些dp的转移方程,我们可以 ...

  10. 「学习笔记」递推 & 递归

    引入 假设我们想计算 \(f(x) = x!\).除了简单的 for 循环,我们也可以使用递归. 递归是什么意思呢?我们可以把 \(f(x)\) 用 \(f(x - 1)\) 表示,即 \(f(x) ...

随机推荐

  1. install package within python

    import os os.system("pip install numpy") import subprocess subprocess.call(['pip3', 'insta ...

  2. python之自动化连连看脚本-第一关不动-小记

    (如想转载,请联系博主或贴上本博地址) 仅供学习python之用,勿用做商业用途.运行环境为1920*1080屏幕,python3.7,win7,谷歌浏览器版本 75.0.3770.100. 参考ht ...

  3. ls和mkdir

    ls  查看当前目录的内容 1) ls -l 显示详细列表 2) Ls -lh 吧文件大小以人性化的方式展开 3) ls -a 显示所有的文件,包括隐藏文件,隐藏文件是已.开头的文件 4) ll 等于 ...

  4. binder机制分析

    1. binder基本概念 1.1 特点 1)binder 是一种基于C/S通信模式的IPC(Inter_Process Communication). 2)在传输过程中近需要一次copy,为发送添加 ...

  5. keras图片数字识别入门AI机器学习

    通过使用mnist(AI界的helloworld)手写数字模型训练集,了解下AI工作的基本流程. 本例子,要基于mnist数据集(该数据集包含了[0-9]的模型训练数据集和测试数据集)来完成一个手写数 ...

  6. ACM需要知道的STL小技巧

    天天用stl,但是有一些小技巧如果不知道,偶尔会导致TLE,这里说几个打比赛需要用到的. 主要是大概了解一下其底层原理:https://www.jianshu.com/p/834cc223bb57 就 ...

  7. Java项目是不是分布式,真有那么重要吗?

    大家好,我是3y啊. 大概不知道从什么时候,「微服务」「分布式」这两个词又再次频繁出现在我的视线里. 「微服务」「分布式」在我刚毕业的时候还是比较关注的,那时候还入门了一把SpringCloud,写了 ...

  8. Go语言:利用 TDD 测试驱动开发帮助理解数组与动态数组(切片)的区别

    Array VS Slice 数组允许你以特定的顺序在变量中存储相同类型的多个元素. 对于数组来说,最常见的就是迭代数组中的元素. 我们创建一个 Sum 函数,它使用 for 来循环获取数组中的元素并 ...

  9. Web 开发的常规流程

    Web 开发的常规流程 What is the Web? 简单地说,网络是一个遍布全球的网络,它连接大量设备并允许它们相互通信 Internet 上的网站托管在称为服务器的设备上,当您与 Intern ...

  10. 基于OpenAI的代码编辑器,有点酷有点强!

    最近随着OpenAI的一系列大动作,把软件领域搅的天翻地覆.各行各业各领域,都出现了大量新产品. 开发工具领域首当其冲,各种新工具层出不穷,今天TJ就给大家推荐一个全新的开发工具:Cursor 从官网 ...