初学SPFA

狂风中的少年 提交于 2019-11-28 00:49:33

SPFA 算法是Bellman-Ford算法的队列优化算法的别称,在国际上被称为“队列优化的Bellman-Ford算法”,仅在中国被称为SPFA算法。也就是说,这是Bell-man Ford的升级版(虽说本人也不会Bellman-Ford)。SPFA通常用于求含负权边的单源最短路径,以及判负权环。SPFA的时间复杂度一般为O(km)。但由于这种算法的过于玄学,当有人故意卡你时,可能会变成O(nm),所以请慎用。

例题

题目描述

小Q非常喜欢在自己的国家旅行。小Q所在的国家有N座城市,分别编号为1~n,小Q所在的城市编号为1。小Q现在想知道从他所在的城市出发,到其他N-1个城市的最短路程分别是多少?

输入

第一行两个整数N,M(1<=n<=1000,1<=M<=100000),分别表示小Q所在的国家有N座城市以及城市间有M条单向道路。
接下来M行,每行三个整数x,y,len(1<=x,y<=n,1<=len<=100000)表示从城市x去到城市y需要走len这么多路程。
输入可能存在重边

输入

一共N-1行,每行一个整数,第i个整数表示小Q从城市1到城市(i+1)的最短路程。如果不能到达输出-1

样例输出

4 4
1 2 3 2
3 4 1 3
2 2 4 1

样例输出

 3
 2
 4

代码实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node
{
    int ver;
    int edge;
    int next;
    
};
node d[100001];
queue <int> q;
int tot,x,y,z,dis[1001],head[100001],n,m;
bool v[100001];
void add(int a,int b,int c)//构建邻接表
{
    tot++;
    d[tot].ver=y;
    d[tot].edge=z;
    d[tot].next=head[x];
    head[x]=tot;
}
void spfa()
{
    memset(dis,0x3f3f3f,sizeof(dis));
    memset(v,false,sizeof(v));
    dis[1]=1;
    v[1]=true;
    q.push(1);
    while(q.size())//每次取出队头
    {
        int x=q.front();
        q.pop();
        v[x]=false;//扫描所有边
        for(int i=head[x];i;i=d[i].next)
        {
            int a=d[i].ver;
            int b=d[i].edge;
            if(dis[a]>dis[x]+b)//跟新最优解
            {
                dis[a]=dis[x]+b;
                if(!v[a])
                {
                    q.push(a);
                    v[a]=true;
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    spfa();
    for(int i=2;i<=n;i++)
        printf("%d\n",dis[i]-1);
    return 0;
}

 

本次内容就到这里了,请各位朋友,有时间的给个赞,没时间的留个心,谢谢大家!

本次内容就到这里了,请各位朋友,有时间的给个赞,没时间的留个心,谢谢大家!

本次内容就到这里了,请各位朋友,有时间的给个赞,没时间的留个心,谢谢大家!

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!