最短路径问题的Dijkstra和SPFA算法总结

Dijkstra算法:

解决带非负权重图的单元最短路径问题。时间复杂度为O(V*V+E)

算法精髓:维持一组节点集合S,从源节点到该集合中的点的最短路径已被找到,算法重复从剩余的节点集V-S中选择最短路径估计最小的节点u,对u的所有连边进行松弛操作。即对j=1~n,dis[j] = min(dis[j],dis[k]+map[k][j])。

常规代码如下:

void Dijkstra()
{
    int i,j,k,mini;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++)
        d[i] = Mod;
    d[s] = 0;     //源点距离为0
    for(i=1;i<=n;i++)
    {
        mini = Mod;
        for(j=1;j<=n;j++)         //找最短路径估计最小的节点k
        {
            if(!vis[j] && d[j] < mini)
            {
                k = j;
                mini = d[j];
            }
        }
        vis[k] = 1; 
        for(j=1;j<=n;j++)       //松弛操作
        {
            if(mp[k][j] != Mod && d[j] > d[k] + mp[k][j])  //mp[k][j] != Mod 也可写成 !vis[j]
                d[j] = d[k] + mp[k][j];
        }
    }
}
View Code

 

SPFA算法:

实际是用队列优化的Bellman-ford算法,可以允许负边权的存在。SPFA算法通过维护一个队列,使得一个节点的当前最短路径被更新之后没有必要立刻去更新其他的节点,从而大大减少了重复的操作次数。在负边权和稀疏图上可完全替代Bellman-ford算法,但是与Dijkstra算法与Bellman-ford算法都不同,SPFA的算法时间效率是不稳定的,即它对于不同的图所需要的时间有很大的差别。在非负边权上最好还是用性能稳定的Dijkstra算法。时间复杂度O(kE){k<<V}。

常规代码如下:

//边用vector<pait<int,int> > 存储
void SPFA(int s)
{
    int u,v,i;
    int len;
    for(i=0;i<=n;i++)
    {
        inq[i] = 0;
        dis[i] = Mod;
    }
    dis[s] = 0;
    while(!que.empty())
        que.pop();
    que.push(s);
    while(!que.empty())
    {
        u = que.front();
        que.pop();
        inq[u] = 0;
        for(i=0;i<edge[u].size();i++)
        {
            v = edge[u][i].first;
            len = edge[u][i].second;
            if(dis[v] > len + dis[u])
            {
                dis[v] = len + dis[u];
                if(!inq[v])
                {
                    inq[v] = 1;
                    que.push(v);
                }
            }
        }
    }
}
View Code
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值