关于SPFA算法的优化方式

关于SPFA算法的优化方式

这篇随笔讲解信息学奥林匹克竞赛中图论部分的求最短路算法SPFA的两种优化方式。学习这两种优化算法需要有SPFA朴素算法的学习经验。在本随笔中SPFA朴素算法的相关知识将不予赘述。

上课!

No.1 SLF优化(Small Label First)

顾名思义,这种优化采用的方式是把较小元素提前。

就像dijkstra算法的堆优化一样。我们在求解最短路算法的时候是采取对图的遍历,每次求最小边的一个过程,为了寻找最小边,我们需要枚举每一条出边,如果我们一上来就找到这个边,那当然是非常爽的。一次找一次爽,一直找一直爽。所以我们采用了这种优化方式。

具体实现方式是把原来的队列变成双端队列,如果新入队的元素比队首元素还要小,就加入到队首,否则排到队尾。

模板如下:

void spfa()
{
    memset(dist,0x3f,sizeof(dist));
    memset(v,0,sizeof(v));
    deque<int> q;
    q.push_back(1);
    v[1]=1;
    dist[1]=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop_front();
        v[x]=0;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(dist[y]>dist[x]+val[i])
            {
                dist[y]>dist[x]+val[i];
                if(v[y]==0)
                {
                    if(dist[y]<=dist[q.pront()])
                        q.push_front(y);
                    else
                        q.push_back(y);
                    v[y]=1;
                }
            }
        }
    }
}

No.2 LLL优化(Large Label Last)

顾名思义,它的策略是把大的元素放到后面。

你会说,这不跟上面的一样么?

不不不,这个优化针对的是出队元素。它的实现过程是:对于每个出队元素,比较它的dist[]和队列中dist的平均值,如果它的dist[]更大,将它弹出放到队尾。以此类推,直至dist[x]小于其平均值。

模板:

void spfa()
{
    memset(dis, 0x3f, sizeof(dis));
    queue<int> q;
    q.push(1);
    v[1] = 1;
    dist[1] = 0;
    cnt = 1;
    while(!Q.empty())
    {
        int x = q.front();
        while (dis[x]*cnt > sum)
        {
            q.pop();
            q.push(x);
            x = q.front();
        }
        q.pop();
        cnt--;
        sum -= dist[x];
        v[x] = 0;
        for (int i = head[x]; i ; i=nxt[i])
        {
            int y=to[i];
            if (dist[y] > dist[x] + val[i])
            {
                dist[y] = dist[x] + val[i];
                if (v[y]==0)
                {
                    q.push(y);
                    sum += dist[y];
                    cnt++;
                }
            }
        }
    }
}

重点来了!!

No.3 SLF+LLL同时优化!

听名字就很高级。

是的,的确很高级,不仅高级,而且快。

我就直接上模板了。

void spfa()
{
    memset(dist, 0x3f, sizeof(dist));
    memset(v,0,sizeof(v));
    deque<int> q;
    q.push_back(1);
    v[1] = 1;
    dist[1] = 0;
    cnt = 1;
    while (!q.empty())
    {
        int x = q.front();
        while (cnt*dist[x] > sum)
        {
            q.pop_back();
            q.push_back(x);
            x = q.front();
        }
        q.pop_front();
        cnt--;
        sum -= dist[x];
        v[x] = 0;
        for (int i = head[x]; i ; i=nxt[i])
        {
            int y=to[i];
            if (dist[y] > dist[x] + val[i])
            {
                dist[y] = dist[x] + val[i];
                if (!v[y])
                {
                    if (dist[y] <= dist[q.front()])
                        q.push_front(y);
                    else
                        q.push_back(y);
                    v[y] = 1;
                    sum += dist[y];
                    cnt++;
                }
            }
        }
    }
}

下课!祝同学们AK IOI!!

原文地址:https://www.cnblogs.com/fusiwei/p/11289019.html

时间: 2024-10-07 05:27:04

关于SPFA算法的优化方式的相关文章

POJ 3013 Big Christmas Tree【最短路变形,DIjkstra堆优化+spfa算法】

Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23064   Accepted: 4987 Description Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of t

SPFA算法及其应用和优化

by mps [问题引入] 又是一年春运时,因为睡懒觉而导致抢不到票的你,只能打车回家了,而无疑会消耗许多钱财(黑车...),为了尽可能的节省钱,你希望走的是最短路,路途中会经过n个城市,而你每次经过两个城市之间的高速公路时,都会损耗Ci元,假设其中包含了所有的价钱(邮费,过桥费之类的),你现在在1号城市,希望到达n号城市去,请问最少花费是多少? [输入描述] 第一行,n,m,表示有n个城市,m条高速公路 第二行至第m+1行,每行三个数u,v,w,表示u城市到达v城市的耗费为w元(均为有向边)

EOJ 1848 你是ACM吗? 用二叉堆优化dijkstra + spfa算法的学习

Description  随着中国经济的腾飞,中国的物流产业迎来了发展的春天.特别是在上海这样一个拥有广阔国内腹地的国际化大都市,物流业以空前的速度膨胀. 当然是大蛋糕就会吸引许多馋嘴猫,馋嘴猫多了就会有残酷的竞争.当大量资金流入物流产业时,KOP 集团为了稳坐在国内物流业的第一把交椅,决定对现行的运输方案进行改良,以减少自己的成本同时使其它竞争者知难而退. 作为世界100强的KOP集团当然知道要找到最优运输方案,肯定得靠数学和算法很好的软件工程师,于是他们理所当然地找到华东师范大学软件学院.决

POJ 1511 Invitation Cards 【最短路,spfa算法,Dijkstra算法堆优化】

Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 25219   Accepted: 8346 Description In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They wan

spfa算法详解

program: #include<cstdio> using namespace std; struct node {int x; int value; int next; }; node e[60000]; int visited[1505],dis[1505],st[1505],queue[1000]; int main() { int n,m,u,v,w,start,h,r,cur; freopen("c.in","r",stdin); freo

Cocos2d-x 地图行走的实现2:SPFA算法

上一节<Cocos2d-x 地图行走的实现1:图论与Dijkstra算法> http://blog.csdn.net/stevenkylelee/article/details/38408253 本节实践另一种求最短路径算法:SPFA 1.寻路算法实现上的优化 上一节我们实现的Dijkstra用了一个哈希表来保存搜索到的路径树.如果能用直接的访问的方式,就不要用哈希表,因为直接访问的方式会比哈希表更快.我们修改一下图顶点的数据结构.如下: /* 图顶点 */ class Vertex { fr

最短路:spfa算法

板子补完计划绝赞继续中( 这篇博客就来写一写spfa(这我居然板子都打错了一次,我太弱啦!) 先来看一下定义:(引自http://blog.csdn.net/juststeps/article/details/8772755) 首先说明,SPFA是一种单源最短路径算法,所以以下所说的"某点的最短路径长度",指的是"某点到源点的最短路径长度". 我们记源点为S,由源点到达点i的"当前最短路径"为D[i],开始时将所有D[i]初始化为无穷大,D[S]

最短路径--SPFA 算法

适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径一定存在.当然,我们可以在执行该算法前做一次拓扑排序,以判断是否存在负权回路,但这不是我们讨论的重点. 算法思想:我们用数组d记录每个结点的最短路径估计值,用邻接表来存储图G.我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计

算法笔记_071:SPFA算法简单介绍(Java)

目录 1 问题描述 2 解决方案 2.1 具体编码   1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个顶点,称为起点,求取起点到其它所有顶点之间的最短距离,其显著特点是可以求含负权图的单源最短路径,且效率较高.(PS:引用自百度百科:spfa是求单源最短路径的一种算法,它还有一个重要的功能是判负环(在差分约束系统中会得以体现),在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛