关于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. 系统重装助手教你如何在Microsoft Edge中恢复“关闭所有选项卡”警告

    在Microsoft Edge中,当您打开多个选项卡时,浏览器将显示“您要关闭所有选项卡吗?” 警告,以防止您意外关闭重要标签. 通常,在没有第二个想法的情况下,您会立即禁用此功能,检查提示中的“始终 ...

  2. windows下查看端口被占用及处理

    一.通过命令行查找端口被谁占用 1.window+R组合键,调出命令窗口 2.输入命令:netstat -ano,列出所有端口的情况.在列表中我们观察被占用的端口 3.查看被占用端口对应的PID,输入 ...

  3. 如何在Spring Data JPA中引入Querydsl

    一.环境说明 基础框架采用Spring Boot.Spring Data JPA.Hibernate.在动态查询中,有一种方式是采用Querydsl的方式. 二.具体配置 1.在pom.xml中,引入 ...

  4. eclipse中跳转到其它函数方法后如何快速返回原处

    快捷键 ctrl + 鼠标左键:跳转到引用的方法 alt + left :从所跳转到引用的方法返回原方法 alt + right:从原处返回到引用的方法

  5. sqlalchemy外键的一些东西

    sqlalchemy中让MySQL支持中文字符 engine = create_engine("mysql+pymysql://root:mysql8@localhost/mysqltest ...

  6. bibli直播弹幕实时爬取

    1 分析数据来源  在不知道弹幕信息在哪里的时候,只能去all里面查看每一个相应的信息,看信息是否含有弹幕信息 在知道弹幕信息文件的时候,我们可以直接用全局文件搜索,定位到弹幕数据文件.操作如下图 2 ...

  7. echarts之legend-改变图例的图标为自定义图片

    legend:{ show:true, orient:'horizontal', borderColor:'#df3434', borderWidth:2, data:[ { name:'蒸发量', ...

  8. mysql 有没有参数都报错“mysql: unknown option”

    报错: [root@XXXX tmp]# mysql -uroot -pmysql: unknown option '--You have new mail in /var/spool/mail/ro ...

  9. 10分钟,AppCan帮你搞定跨平台开发APP问题!

    跨平台开发APP时,开发者总会遇到一些问题,如打包失败等等,尤其对于iOS来说,由于它的限制性会导致一些状况发生(如证书上传问题等),小编总结了几个AppCan在线IOS打包失败常见的情况及排查技巧, ...

  10. linux查询日志常用命令,经常更新

    1.grep命令 grep -c "查询内容" filename    ------c,是小写,可以知道你要查询的内容在这个文件中是否存在 grep -C 10 "查询内 ...