基于各种基础数据结构的SPFA和各种优化
一、基于各种数据结构的SPFA
以下各个数据均为不卡SPFA的最短路模板:P3371 【模板】单源最短路径(弱化版)的测试时间
1、STL队列:用时: 1106ms / 内存: 8496KB
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[];
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
queue<int>q;
q.push(s);
vis[s]=;
dist[s]=;
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
q.push(y);
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
read();
spfa(s);
pr();
return ;
}
2、STL栈:用时: 4257ms / 内存: 8536KB(#2,#9,#10TLE)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[];
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
stack<int>q;
q.push(s);
vis[s]=;
dist[s]=;
while(!q.empty())
{
int t=q.top();
q.pop();
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
q.push(y);
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
read();
spfa(s);
pr();
return ;
}
3、模拟栈:用时: 4242ms / 内存: 8508KB(#2,#9,#10TLE)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[],stk[],top;
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
top=;
stk[top]=s;
vis[s]=;
dist[s]=;
while(top>)
{
int t=stk[top];
top--;
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
stk[++top]=y;
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
read();
spfa(s);
pr();
return ;
}
4、STL优先队列:用时: 1377ms / 内存: 8612KB
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[],stk[],top;
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
priority_queue<int>q;
q.push(s);
vis[s]=;
dist[s]=;
while(!q.empty())
{
int t=q.top();
q.pop();
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
q.push(y);
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
read();
spfa(s);
pr();
return ;
}
时间总的来说是这个样子的:STL栈>模拟栈>STL优先队列>STL队列
二、SPFA的优化
SPFA目前常见的优化有3种,分别是:SLF优化,LLL优化,随机优化。
1、SLF优化:
SLF优化采取的策略是开一个双端队列,如果即将入队节点大于队首值就插入前端,否则插入后端。是最常见的也是最好用的SPFA优化方法
用时: 1100ms / 内存: 8512KB
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[],sum;
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
deque<int>q;
q.push_back(s);
vis[s]=;
dist[s]=;
while(!q.empty())
{
int t=q.front();
q.pop_front();
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
if(dist[y]<=dist[q.front()])q.push_front(y);
else q.push_back(y);
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
read();
spfa(s);
pr();
return ;
}
2、LLL优化:
LLL优化也是开一个双端队列,每次去队首看是否大于平均值,大于就插入队尾继续寻找。看起来高大上实际应用不多的SPFA优化
用时: 1114ms / 内存: 8500KB
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[],sum;
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
deque<int>q;
q.push_back(s);
vis[s]=;
dist[s]=;
while(!q.empty())
{
int t=q.front();
if(dist[t]*q.size()>sum)
{
q.pop_front();
q.push_back(t);
continue;
}
q.pop_front();
sum-=dist[t];
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
q.push_back(y);
sum+=dist[y];
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
read();
spfa(s);
pr();
return ;
}
3、随机优化:
随机优化就是rand一下,为0插入队首,为1插入队尾,最不靠谱的优化。
用时: 1259ms / 内存: 8516KB
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cstring>
#include<queue>
#include<algorithm>
#define inf 336860180
using namespace std;
int n,m,s,x,y,z,v[],w[],head[],nxt[],cnt,maxx,dist[],sum;
bool vis[];
void add(int a,int b,int c)
{
v[++cnt]=b;
w[cnt]=c;
nxt[cnt]=head[a];
head[a]=cnt;
}
void read()
{
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add(x,y,z);
}
}
void spfa(int s)
{
memset(dist,,sizeof(dist));
deque<int>q;
q.push_back(s);
vis[s]=;
dist[s]=;
while(!q.empty())
{
int t=q.front();
q.pop_front();
vis[t]=;
for(int i=head[t];i;i=nxt[i])
{
int y=v[i];
if(dist[y]>dist[t]+w[i])
{
dist[y]=dist[t]+w[i];
if(!vis[y])
{
if(rand()%)q.push_front(y);
else q.push_back(y);
vis[y]=;
}
}
}
}
}
void pr()
{
for(int i=;i<=n;i++)
{
if(dist[i]!=inf)cout<<dist[i];
else cout<<"";
cout<<" ";
}
}
int main()
{
srand(time(NULL));
read();
spfa(s);
pr();
return ;
}
优化后的时间排序:RAND>LLL>朴素>SLF
如果你喜欢我的文章就来个点赞收藏转发关注吧!!!
基于各种基础数据结构的SPFA和各种优化的更多相关文章
- Vlc基础数据结构记录
1. Vlc基础数据结构 hongxianzhao@hotmail.com 1.1 基础数据结构 struct vlc_object_t,相关文件为src\misc\objects.c. 定义为: ...
- Flink内存管理源代码解读之基础数据结构
概述 在分布式实时计算领域,怎样让框架/引擎足够高效地在内存中存取.处理海量数据是一个非常棘手的问题.在应对这一问题上Flink无疑是做得非常杰出的,Flink的自主内存管理设计或许比它自身的知名度更 ...
- redis 基础数据结构实现
参考文献 redis数据结构分析 Skip List(跳跃表)原理详解 redis 源码分析之内存布局 Redis 基础数据结构与对象 Redis设计与实现-第7章-压缩列表 在redis中构建了自己 ...
- redis基础数据结构及编码方式
redis基础数据结构和编码方式 一.基础数据结构 1)简单动态字符串 2)双端链表 3)字典 4)跳跃表 5)整数集合 6)压缩列表 二.对象类型与编码 在redis的数据库中创建一个新的键值对时, ...
- Redis基础——剖析基础数据结构及其用法
这是一个系列的文章,打算把Redis的基础数据结构.高级数据结构.持久化的方式以及高可用的方式都讲一遍,公众号会比其他的平台提前更新,感兴趣的可以提前关注,「SH的全栈笔记」,下面开始正文. 如果你是 ...
- 基于php基础语言编写的小程序之计算器
基于php基础语言编写的小程序之计算器 需求:在输入框中输入数字进行加.减.乘.除运算(html+php) 思路: 1首先要创建输入数字和运算符的输入框,数字用input的text属性,运算符用sel ...
- 【UOJ#228】基础数据结构练习题 线段树
#228. 基础数据结构练习题 题目链接:http://uoj.ac/problem/228 Solution 这题由于有区间+操作,所以和花神还是不一样的. 花神那道题,我们可以考虑每个数最多开根几 ...
- 理解 OpenStack + Ceph (4):Ceph 的基础数据结构 [Pool, Image, Snapshot, Clone]
本系列文章会深入研究 Ceph 以及 Ceph 和 OpenStack 的集成: (1)安装和部署 (2)Ceph RBD 接口和工具 (3)Ceph 物理和逻辑结构 (4)Ceph 的基础数据结构 ...
- hrbustoj 1551:基础数据结构——字符串2 病毒II(字符串匹配,BM算法练习)
基础数据结构——字符串2 病毒IITime Limit: 1000 MS Memory Limit: 10240 KTotal Submit: 284(138 users) Total Accepte ...
随机推荐
- jQuery学习总结04-文档处理
1.append(content|fn) 说明:向每个匹配的元素内部追加内容. 这个操作与对指定的元素执行appendChild方法,将它们添加到文档中的情况类似. content(要追加到目标中的内 ...
- nodejs 更新代码自动刷新页面
安装第三方工具: nodemon npm install --global nodemon 安装完毕后使用: 之前使用: node xxx.js 改成 nodemon xxx.js 只要通过nodem ...
- 第一次写的MySQLHelper
一. 第一次写MysqlHelper,用来管理城市的数据库 二.MySQLHelper源代码 using MySql.Data.MySqlClient; using System; using Sys ...
- python的list内存分配算法
前提:python为了提高效率会为list预先分配一定的内存空间供其使用,避免在每次append等操作都去申请内存,下面简单分析下list的内存分配算法,主要就是两段. 1.当没有元素时,newsiz ...
- #10042. 「一本通 2.1 练习 8」收集雪花 || 离散化 || 双指针法 || C++ || LOJ
题目:#10042. 「一本通 2.1 练习 8」收集雪花 看到网上没有这道题的题解,所以写一下. 要标记数字是否存在,看到x<=1e9,所以考虑用离散化,然后开一个last数组,last[i] ...
- 【LeetCode】二分 binary_search(共58题)
[4]Median of Two Sorted Arrays [29]Divide Two Integers [33]Search in Rotated Sorted Array [34]Find F ...
- Thinkphp 请求和响应
一. Request对象获取方法 1. request() 助手函数获取 2. think\Request 类获取 3.利用框架注入Request对象 Request方法时单利方法 在think框架 ...
- vue兄弟组件之前传信
1.使用vuex 2.子传父,父传子 3.使用中央事件总线 1.新建一个js文件,然后引入vue 实例化vue 最后暴露这个实例 2.在要用的组件内引入这个组件 3.通过vueEmit.$emit(' ...
- Java缓冲流写出数据实例
public class BufferedWriterDemo throws IOException { public static void main(String[] args) throws I ...
- 牛客多校第一场 Random Point in Triangle
https://ac.nowcoder.com/acm/contest/881/F 打表代码: #include<bits/stdc++.h> using namespace std; ] ...