关于SLF优化

朴素SPFA使用常规队列(FIFO)更新距离,并没有考虑优化出队顺序(dis值小的优先出队)可以在一开始就把各个点的dis值限值小,从而避免大量的松弛操作,从而提高效率。这就是SLF(Small Label First)

实现方式很简单,常规队列替换为双端队列(deque),对于一个要加入的点u,如果dis[u]<dis[Q.front()]u就放入队首,否则放入队尾。

此外还有LLL(Large Label first)优化,思路是对每个要出队的元素u,比较dis[u]和队列中所有dis值的平均值,如果dis[u]大,那么将它弹出放到队尾,取队首元素再重复判断,直达存在dis[u]小于平均值。发现没有,LLLSLF的目的是一样的。

当然,可以把这两种优化组合起来。

STL双端队列

  • 全称:“double-ended queue”,deque是双端数组,而vector是单端的
  • 在操作方式上和vector相似
  • 可以随机存取元素(用[]操作符或at()方法)
  • 头部和尾部添加或移除元素非常快,在中部插入或删除元素比较慢
  • 需要添加头文件<deque>
//定义
deque<int> dq1; //一个存放int的deque容器
deque<double> dq2; //一个存放float的deque容器
deque<string> de3; //一个存放string的deque容器。
//添加移除
dq1.push_back(elem); //在容器尾部添加一个元素
dq1.push_front(elem); //在容器头部插入一个元素
dq1.pop_back(); //删除容器最后一个元素
dq1.pop_front(); //删除容器第一个元素
//存取
cout<<dq1.at(pos); //返回pos位置的元素,如果pos越界,抛出out_of_range异常
cout<<dq1[pos]; //返回pos位置的元素,如果pos越界,一般情况下RE
dq1[pos]=1;
cout<<dq1.front(); //返回第一个元素
cout<<dq1.back(); //返回最后一个元素
//迭代器
dq1.begin(); //返回容器中第一个元素的迭代器
dq1.end(); //返回容器中最后一个元素之后的迭代器
dq1.rbegin(); //返回容器中倒数第一个元素的迭代器
dq1.rend(); //返回容器中倒数最后一个元素之后的迭代器
//大小
dq1.size(); //返回容器中元素的个数
dq1.empty(); //判断容器是否为空
dq1.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
dq1.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
//带参数构造
deque<int> dqx(dq1.begin(), dq1.end()); //用dq1 [beg, end)区间中的元素初始化dqx
deque<int> dqy(n, elem); //用n个elem初始化dqx
deque<int> dqz(dq1); //拷贝构造函数,用dq1初始化dqz
//赋值
deque<int> dqm, dqn;
dqm.assign(dq1.begin(), dq1.end()); //将dq1 [beg, end)区间中的数据拷贝给dqm
dqn.assign(n, elem); //将n个elem拷贝赋值给dqn
dqn=dqm; //整体拷贝
dqn.swap(de1); //整体交换
//插入
dq1.insert(pos, elem); //pos位置插入elem
dq1.insert(pos, n, elem); //pos位置插入n个elem
dq1.insert(pos, beg, end); //pos位置插入迭代器[begin, end)之间的元素
//删除
dq1.clear(); //清空
dq1.erase(beg, end); //删除[beg,end)区间的元素,返回下一个元素的位置
dq1.erase(pos); //删除pos位置的元素,返回下一个元素的位置

//SPFA+SLF
#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
using namespace std;
const int maxn=1e4+5, maxm=5e5+5, INF=2147483647;
int dis[maxn], v[maxn], n, m, s;
struct edge{
int t, w; edge *nxt;
edge(int to, int len, edge *next){ t=to, w=len, nxt=next; }
};
edge *h[maxn];
void add(int x, int y, int z){ h[x]=new edge(y, z, h[x]); } void SPFA(int s)
{
for(int i=1; i<=n; i++) dis[i]=(i==s) ? 0 : INF;
deque<int> Q; //Q为双端队列
Q.push_back(s), v[s]=1;
while(!Q.empty())
{
int x=Q.front(); Q.pop_front(); v[x]=false; //v数组用以标记点i是否在队列中
for(edge *p=h[x]; p; p=p->nxt)
if(dis[p->t]>dis[x]+p->w)
{
dis[p->t]=dis[x]+p->w;
if(!v[p->t])
{
v[p->t]=1;
if(Q.empty() || dis[p->t]>dis[Q.front()]) Q.push_back(p->t);
else Q.push_front(p->t);
}
}
}
} int main()
{
scanf("%d%d%d", &n, &m, &s);
for(int i=1, x, y, z; i<=m; i++) scanf("%d%d%d", &x, &y, &z), add(x,y,z);
SPFA(s);
for(int i=1; i<=n; i++) printf("%d ",dis[i]);
return 0;
}

//SPFA+SLF+LLL
#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
using namespace std;
const int maxn=1e4+5, maxm=5e5+5, INF=2147483647;
int dis[maxn], v[maxn], n, m, s;
struct edge{
int t, w; edge *nxt;
edge(int to, int len, edge *next){ t=to, w=len, nxt=next; }
};
edge *h[maxn];
void add(int x, int y, int z){ h[x]=new edge(y, z, h[x]); } void SPFA(int s)
{
int cnt=0, sum=0; //cnt为队列中元素个数,sum为队列中dis值总和
for(int i=1; i<=n; i++) dis[i]=(i==s) ? 0 : INF;
deque<int> Q; //Q为双端队列
Q.push_back(s), v[s]=1, cnt=1;
while(!Q.empty())
{
int x=Q.front();
while(cnt*dis[x]>sum) //取出来,放后去,直到找到一个比平均值小的点
{
Q.pop_front();
Q.push_back(x);
x=Q.front();
}
Q.pop_front();
cnt--, sum-=dis[x], v[x]=false; //出队后,更新队列大小及队列dis值之和
for(edge *p=h[x]; p; p=p->nxt)
if(dis[p->t]>dis[x]+p->w)
{
dis[p->t]=dis[x]+p->w;
if(!v[p->t])
{
v[p->t]=1;
if(Q.empty() || dis[p->t]>dis[Q.front()]) Q.push_back(p->t);
else Q.push_front(p->t);
cnt++, sum+=dis[p->t]; //入队后,更新队列大小及队列dis值之和
}
}
}
} int main()
{
scanf("%d%d%d", &n, &m, &s);
for(int i=1, x, y, z; i<=m; i++) scanf("%d%d%d", &x, &y, &z), add(x,y,z);
SPFA(s);
for(int i=1; i<=n; i++) printf("%d ",dis[i]);
return 0;
}

SPFA+SLF+LLL的更多相关文章

  1. SPFA+SLF+LLL优化模板

    #include<algorithm> #include <iostream> #include <cstdlib> #include <cstring> ...

  2. Dijkstra、Dij + heap、Floyd、SPFA、 SPFA + SLF Template

    Dijkstra in Adjacency matrix : int Dijkstra(int src,int tec, int n){ ]; ]; memset(done,,sizeof(done) ...

  3. [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  4. POJ - 3268 Silver Cow Party SPFA+SLF优化 单源起点终点最短路

    Silver Cow Party One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to ...

  5. spfa + slf优化

    最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 . QwQ,所以就去学了一下优化 . slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我t ...

  6. 2013成都邀请赛J称号||HDU4725 The Shortest Path in Nya Graph(spfa+slf最短的优化)

    职务地址:HDU 4725 这题卡了好长时间了,建图倒是会建,可是不会最短路的算法优化,本以为都须要堆去优化的,打算学了堆之后再来优化.可是昨晚CF的一道题..(那题也是不优化过不了..)然后我就知道 ...

  7. 初识费用流 模板(spfa+slf优化) 餐巾计划问题

    今天学习了最小费用最大流,是网络流算法之一.可以对于一个每条边有一个容量和一个费用(即每单位流的消耗)的图指定一个源点和汇点,求在从源点到汇点的流量最大的前提下的最小费用. 这里讲一种最基础也是最好掌 ...

  8. SPFA的两个优化:SLF与LLL

    先举出个例题:洛谷P3371 [模板]单源最短路径 一眼扫去:最短路径. spfa不接受反驳... 附上代码: #include<iostream> #include<algorit ...

  9. 【最短路径】 常用算法图解+1376:信使(msner)六解

    进入图之后,最短路径可谓就是一大重点,最短路径的求法有很多种,每种算法各有各的好处,你会几种呢?下面来逐个讲解. 1 floyed算法 1)明确思想及功效:在图中求最短路还是要分开说的,分别是单源最短 ...

随机推荐

  1. markdown小知识总结

    字体.字号.颜色 但如果我们想修改文字大小/颜色/字体,就要用font标签,代码如下: 宋体大小为2的字 color代表字体颜色(要用16进制颜色值),size代表文字大小,face代表字体 效果展示 ...

  2. Docker:测试环境的准备-建立一台centos测试机

    一.安装虚拟机并配置网络,下面演示在一台工作机上搭建环境 基础准备: 安装VMware-workstation-full-15.0.0-10134415.exe 安装虚拟机,镜像文件:CentOS-7 ...

  3. kafka-rest:怎么愉快的build?

    愉快的build该项目吧 git clone https://github.com/confluentinc/kafka-restmvn clean install -Dmaven.test.skip ...

  4. 关于使用国内dock仓库,网易、DaoCloud

    使用国内docker镜像仓库,大大提高镜像的下载速度,从docker hub下载慢的不要不要的,甚至根本下载不了镜像,在docker for windows 18.06中增加一个配置即可,非常简单,具 ...

  5. 倒计时js

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. linux下安装nodejs及npm

    转:https://www.cnblogs.com/wuyoucao/p/7011666.html 1.下载npm包 官网下载npm安装包,https://nodejs.org/en/,左边是稳定版右 ...

  7. redis分页

    模仿的https://www.cnblogs.com/dee0912/p/4612183.html 第一步连接redis后进行添加数据 require_once '../redis/redis.php ...

  8. Oracle Metric sequence load elapsed time

    Oracle Metric sequence load elapsed time The sequence load elapsed time Oracle metric is the amount ...

  9. springBoot中使用定时任务

    简单示例 导入依赖 springBoot已经默认集成了定时任务的依赖,只需要引入基本的依赖就可以使用定时任务. <parent> <groupId>org.springfram ...

  10. IDEA远程调试监控端口

    大家知道,线上环境定位问题不是那么简单的,如果有非常完善的日志以及监控系统是不必担心的,但是应对这些并不完善的场景下,IDEA提供了一种远程调试的功能,remote集成了可以远程调试的功能,只需要在你 ...