SPFA算法

1 篇文章 0 订阅
0 篇文章 0 订阅

SPFA算法

闲聊

今天在网上查关于SPFA的算法的资料发现有好多都是一样的图片什么的都是一样的真尴尬。

我找了一个自认为比较好的按照上面学习,上面有些说法很模糊比如松弛什么的我开始什么都不知道没有一点概念真尴尬

题目描述

给定一个有向图a-g求最短路径

这个图片是我抄别人的
* 这个图片是我抄别人的,表示不会做图

为了更好的写代码我把上面的图片转化成为如下形式

1 2 24
1 3 8
1 4 15
2 5 6
3 5 7
3 6 3
4 7 4
5 7 9
6 7 3
6 4 5
7 2 3
6 5 2

比如第一行 表示的就是A->B他们之间的长度为24

算法简介

SPFA算法是求单源最短路径的一种算法,它是一种十分高效的最短路算法。

很多时候,给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了。SPFA的复杂度大约是O(kE),k是每个点的平均进队次数(一般的,k是一个常数,在稀疏图中小于2)。

但是,SPFA算法稳定性较差,在稠密图中SPFA算法时间复杂度会退化。

实现方法

  1. 建立一个队列,初始时队列里只有起始点
  2. 建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)
  3. 执行松弛操作,用队列里有的点去刷新起始点到所有点的最短路
  4. 如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空。
  5. 此外,SPFA算法还可以判断图中是否有负权环,即一个点入队次数超过N。
    • 第五点还有点不明白

具体实现

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>

#define INF 0x3f
using namespace std;

struct node{
int y;
int quan;

}t;

vector<node>mymap[20];
queue<int>Q;
int d[20];
int xx[20];
int main()
{
    int n=7;
    int l=12;

    memset(d,INF,sizeof(d));
    memset(xx,INF,sizeof(xx));
    /*
1 2 24
1 3 8
1 4 15
2 5 6
3 5 7
3 6 3
4 7 4
5 7 9
6 7 3
6 4 5
7 2 3
6 5 2
    */
    for(int i=1;i<=l;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        t.quan=c;
        t.y=b;
        mymap[a].push_back(t);
    }
    Q.push(1);
    d[1]=0;
    xx[1]=0;
    while(!Q.empty())
    {
        int tmp=Q.front();
        Q.pop();
        xx[tmp]=INF;
        for(unsigned int i=0;i<mymap[tmp].size();i++)
        {
        if(mymap[tmp][i].quan+d[tmp]<d[mymap[tmp][i].y]) //
        {
            d[mymap[tmp][i].y]=mymap[tmp][i].quan+d[tmp];
            if(xx[mymap[tmp][i].y]!=0)
            {
                Q.push(mymap[tmp][i].y);
                xx[mymap[tmp][i].y]=0;
            }
        }

        }
        for(int i=1;i<n+1;i++)
        cout<<d[i]<<"  ";
        cout<<endl;
    }
//    for(int i=1;i<n+1;i++)
//        cout<<d[i]<<"  ";
//    cout<<endl;
    return 0;
}

在代码里面我把每一次更新以后的最短路都打了出来如下:

0  24  8  15  1061109567  1061109567  1061109567  
0  24  8  15  30  1061109567  1061109567  
0  24  8  15  15  11  1061109567  
0  24  8  15  15  11  19  
0  24  8  15  15  11  19  
0  24  8  15  13  11  14  
0  17  8  15  13  11  14  
0  17  8  15  13  11  14  
0  17  8  15  13  11  14  

最后一行就是我们要得a到其他各点的最短路了

作者语

开始的时候我对“”如果刷新成功且被刷新点不在队列中则把该点加入到队列最后“” 这一句话理解有一点问题
这一句话的意思是先刷新如果刷新成功就看这一点是否在队列中如果在队列里面就不入队否则就入队
* 不知道自己说的明白不,我就是这么理解的

版权属于:copie

本文链接:http://copie.cn/index.php/archives/SPFA%E7%AE%97%E6%B3%95.html

转载时须注明出处及本声明

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值