SPFA+SLF+LLL
关于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]小于平均值。发现没有,LLL和SLF的目的是一样的。
当然,可以把这两种优化组合起来。
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的更多相关文章
- SPFA+SLF+LLL优化模板
#include<algorithm> #include <iostream> #include <cstdlib> #include <cstring> ...
- Dijkstra、Dij + heap、Floyd、SPFA、 SPFA + SLF Template
Dijkstra in Adjacency matrix : int Dijkstra(int src,int tec, int n){ ]; ]; memset(done,,sizeof(done) ...
- [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- 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 ...
- spfa + slf优化
最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 . QwQ,所以就去学了一下优化 . slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我t ...
- 2013成都邀请赛J称号||HDU4725 The Shortest Path in Nya Graph(spfa+slf最短的优化)
职务地址:HDU 4725 这题卡了好长时间了,建图倒是会建,可是不会最短路的算法优化,本以为都须要堆去优化的,打算学了堆之后再来优化.可是昨晚CF的一道题..(那题也是不优化过不了..)然后我就知道 ...
- 初识费用流 模板(spfa+slf优化) 餐巾计划问题
今天学习了最小费用最大流,是网络流算法之一.可以对于一个每条边有一个容量和一个费用(即每单位流的消耗)的图指定一个源点和汇点,求在从源点到汇点的流量最大的前提下的最小费用. 这里讲一种最基础也是最好掌 ...
- SPFA的两个优化:SLF与LLL
先举出个例题:洛谷P3371 [模板]单源最短路径 一眼扫去:最短路径. spfa不接受反驳... 附上代码: #include<iostream> #include<algorit ...
- 【最短路径】 常用算法图解+1376:信使(msner)六解
进入图之后,最短路径可谓就是一大重点,最短路径的求法有很多种,每种算法各有各的好处,你会几种呢?下面来逐个讲解. 1 floyed算法 1)明确思想及功效:在图中求最短路还是要分开说的,分别是单源最短 ...
随机推荐
- linux -- 添加、修改、删除路由
在日常的使用中,或者在服务器中,有两个网卡配置两个地址,访问不同的网络段,这种情况是非常常见的现象,但是,我们需要额外的添加路由表来决定发送的数据包经过正确的网关和interface才能正确的进行通信 ...
- Docker 镜像仓库
仓库 仓库(Repository)是集中存放镜像的地方. 一个容易混淆的概念是注册服务器(Registry).实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜 ...
- call()与apply()区别typeof和instanceof的区别
摘自 http://www.cnblogs.com/qzsonline/archive/2013/03/05/2944367.html 一.方法的定义 call方法: 语法:call(thisObj, ...
- springboot + mybatis +pageHelper分页排序
今天下午写查出来的数据的排序,原来的数据没有排序,现在把排序功能加上...原来用的,是xml中的sql动态传参 ,,1个小数没有弄出来,果断放弃... 网上百度一下,发现用pageHelper 可以 ...
- 【Topcoder 1643】PossibleOrders
题意:给一些等价关系,问把所有的数按照大小排序的种类数. 思路:首先并查集维护等价类,然后设有\(n\)个等价类. 那么就可以\(dp\)了. 考虑\(dp(i)\)表示还剩下\(i\)个等价类,答案 ...
- SpringBoot整合RabbitMQ-服务安装
本系列是学习SpringBoot整合RabbitMQ的练手,包含服务安装,RabbitMQ整合SpringBoot2.x,消息可靠性投递实现等三篇博客. 学习路径:https://www.imooc. ...
- Mysql_连接字符串
1.本地数据库连接 <connectionStrings> <add name="ConnectionString" connectionString=" ...
- mysql常见问题处理
出现: Access denied for user ''@'localhost' to database ' 2.error: Found option without preceding grou ...
- day4(分支结构,循环结构,for循环,九九乘法表)
一:复习 ''' 1.变量名命名规范 -- 1.只能由数字.字母 及 _ 组成 -- 2.不能以数字开头 -- 3.不能与系统关键字重名 -- 4._开头有特殊含义 -- 5.__开头__结尾的变量, ...
- Linux中什么是动态网站环境及如何部署
当谈论起网站时,我们可能听说过静态和动态这两个词,但却不知道它们的含义,或者从字面意思了解一些却不知道它们的区别. 这一切可以追溯到网站和网络应用程序,Web应用程序是一个网站,但很多网站不是Web应 ...