最短路径算法(单源)

本文介绍了Bellman-Ford算法处理负权边的能力,其时间复杂度为O(NM),并概述了SPFA算法作为队列优化版本,通过减少冗余计算提高效率,平均时间复杂度为O(kE),其中k为常数。算法使用前向星存储图和vis数组跟踪节点状态。
摘要由CSDN通过智能技术生成

1.bellman-ford算法

能够处理存在负边权的情况。
算法时间复杂度:(NM),N是顶点数,M是边数。
算法实现:
设s为起点,dis[v]即为s到v的最短距离,pre[w]为v前驱。w是边j的长度,且i连接u、v。
初始化:dis[s]=0,dis[v]=∞(v≠s),pre[s]=0
for(i=1;i<=n-1;i++)
    for (j=1;j<=M:j++)
//注意要枚举所有边,不能枚举点。
        if(dis[u[j]]+w[j]<dis[v[j]])
        {
        //u[j]、[v]分别是这条边连接的两个起点与终点。
        dis[v[j]]=dis[u[j]]w[j];
        pre[v[j]]=u[j];//疏通路径
        }
核心思想:看看能否通过w]这条边,使得1号顶点到们号顶点的距离变短。

枚举完一次所有边为一次松弛,那么需要松弛多少次呢?

至多n-1次,通常可能在n-1次前结束;

所以可以在每一次松弛做一个标记,如果这次松弛已经没有可以改变的值了就可结束了;

for(i=1;i<=n-1;i++)
{
    int check=0
    for (j=1;j<=M:j++)
    {
        //注意要枚举所有边,不能枚举点。
        if(dis[u[j]]+w[j]<dis[v[j]])
        {
            //u[j]、[v]分别是这条边连接的两个起点与终点。
            dis[v[j]]=dis[u[j]]w[j];
            check=1;
        }
    }
    if(ckeck==0)break;//没有改变了
}

2.SPFA算法——队列优化的bellman-ford算法


SPFA是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。
主要思想是:
初始时将起点加入队列。每次从队列中取出一个元素,并对所有与它相邻的点进行修改,若某个相邻的点修改成功,则将其入
队。直到队列为空时算法结束。
这个算法,简单的说就是队列优化的bellman-ford,利用了每个点不会更新次数太多的特点发明的此算法。
SP℉A在形式上和广度优先搜索非常类似,不同的是广度优先搜索中一个点出了队列就不可能重新进入队列,但是SPFA中一个
点可能在出队列之后再次被放入队列,也就是说一个点修改过其它的点之后,过了一段时间可能会获得更短的路径,于是再次
用来修改其它的点,这样反复进行下去。
算法时间复杂度:O(kE),E是边数。K是常数,平均值为2。

void SPFA(int t)
{
    queue<int>q;
    memset(dis,0x3f,sizeof(dis));
    dis[t]=0;
    q.push(t);
    vis[t]=1;
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        vis[t]=0;
        for(int i=head[cur];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            if(dis[v>dis[cur]+w])
            {
                dis[cur]=dis[cur]+w;
                if(vis[v]==0)
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}

用的前向星存储图;

vis数组用来判断点是否在队列中;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值