最短路-----spfa(单源最短路)


一、spfa

1、算法

这东西属于bellmen-ford的优化,恕我直言,没看出来,到有点像dijkstra的改版,改成可以判负环的形式,时间复杂度是O(m)->O(n*m)的,看出题人想不想卡了(不过一般情况,只要出题人没问题,他都要卡一下)
开始演示:

设:dist[i]为源点S到i点的路经长度。
由松弛操作我们可知:dist[v] = min(dist[v], dist[u] + w);只有当dist[u]变小的时候,dist[v]才会变小,所以我们可以用变小的点,去更新该点所连通的点。

然后就不演示了,结束!

一句话思想

用已经变小的点去更新可以变小的点

2、如何判负环呢?

记录每一条路径所走的边数,如果边数一共N个点,一条路最多有n-1条边。所以说如果又一条路径的边树>= N,那么就一定有负环。
但是注意,这个负环是从起点走到终点时会出现的负环。有可能一张图上有负环,但你走到终点都遇不到。

二、代码演示

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N=1e5+7;
struct one_tu
{
    int w,next,to;
}tu[N];
int top = 0,head[N];
void build(int u,int v,int w)
{
    top++;
    tu[top] = one_tu{w,head[u],v};
    head[u] = top;
}

int n,m;
int dist[N],cnt[N];//记录路经长度(赋值最大值)、边数(初始值为0)
bool jud[N];//判断是否走过
bool spfa(int s)
{
    memset(dist,0x3f,sizeof(dist));
    dist[s] = 0;
    queue<int> q;
    q.push(s);//添加第一个点
    jud[s] = true;//第一个点入对
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        jud[u] = false;//该点出队,方便进行接下来的更新
        for(int i = head[u]; i; i = tu[i].next)
        {
            int v = tu[i].to, w = tu[i].w;
            if(dist[v] > dist[u] + w)//松弛操作
            {
                dist[v] = dist[u] + w;
                cnt[v] = cnt[u] + 1;//记录走了多少条边
                if(cnt[v] >= n)return true;//存在负环
                if(!jud[v])
                {
                    q.push(v);
                    jud[v] = true;//将减少权值的点入对
                }
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0; i < m; i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        build(u,v,w);
    }
    int s,t;scanf("%d%d",&s,&t);
    if(spfa(s))printf("No\n");
    else printf("%d\n",dist[n]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值