最短路径算法——SPFA算法

在家的这几天效率还是蛮低的,总是有其他的事情耽搁,然后最近就在做搜索题,然后做了两个搜索关于最短路径的,点数少的时候之前学的佛洛依德还能派上点用处,可以点数过1000之后就容易超时了,然后看他们的题解,都用到了一个SPFA算法
SPFA算法是用来求某个点到别的点的距离的最短/最长路径的
算法的整体思路就是使用队列不断地更新点的最短路径知道无法更新为止(感觉和BFS差不多,感觉区别就是进队的数据还是可以继续进队的)
不解释了,直接上代码吧(感觉解释不太明白hhh)
a[i][j]:邻接矩阵,记录邻接点
w[i][j]:权值矩阵,记录边的权值
d[i]:最短路径,记录从开始点到第i个点的最短路径
pre[v] 记录前趋点
exist[i]记录是否能够再一次访问

int head=0,tail=1;
q[1]=s;//s为开始点
exist[s]=true;
while(head!=tail)
{
    u=q[++head];
    exist[u]=false;
    fpr(u的所有临界点v)
    if(d[u]+w[u][v]<d[v])
    {
        d[v]=d[u]+w[u][v];
        pre[v]=u;
        if(!exist[v])
        {q[++tail]=v;exist[v]=true;}
    }
}

上一个例题吧,就上一个博客的那个题,看了题解他们用的双向spfa算法,最后做出来了。原题博客在这儿~~~
首先我们知道这个spfa算法是求出一个开始点到图中每个点的最短路径长度。
在这里插入图片描述
这是样例的图,因为这个题没有权值,所以我们需要对spfa变一变形,让他求出从开始点 开始,经过图中能够经过的新线路最后到达第i个点的最小/最大的水晶球的价格。,然后我们这个题的要求是从1点走到n点能够赚取最多的金钱的值,我们可以通过从i到n的最大水晶球价格减去从1出发到i点的最小水晶球价格最后就是赚取的钱数了。所以这就需要用两次的spfa算法,一次是正向的,一次是反向的。

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int a[100001],tb[100001],ta[100001];
vector<int> g[100001],gf[100001];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;++i)
        cin>>a[i];
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        g[x].push_back(y);   //g是正向建图
        gf[y].push_back(x);  // gf是反向建图
        if(z==2)
        {
            g[y].push_back(x);
            gf[x].push_back(y);
        }
    }
    queue<int> q;
    q.push(1);
    memset(ta,127,sizeof(ta));
    ta[1]=2147483647;
    //记录从1到i结点的最短路径的spfa算法
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        ta[t]=min(ta[t],a[t]);
        int l=g[t].size();
        for(int i=0;i<l;i++)
            if(ta[t]<ta[g[t][i]])
            {
                ta[g[t][i]]=ta[t];
                q.push(g[t][i]);
            }
    }
     //记录从i到n结点的最短路径的spfa算法
    q.push(n);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        tb[t]=max(tb[t],a[t]);
        int l=gf[t].size();
        for(int i=0;i<l;i++)
            if(tb[t]>tb[gf[t][i]]){
                tb[gf[t][i]]=tb[t];
                q.push(gf[t][i]); }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,tb[i]-ta[i]);
	cout<<ans<<endl;
    return 0;
}

最后spfa的时间复杂度O(VE)

真的在家的效率真的是很低了,这个假期想学的还是蛮多的,希望自己的欲望能够战胜理智吧~~~~。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨晓翔同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值