两种最短路算法总结

最短路算法

这里只总结两种最短路算法,第一是:Dijkstra,第二是:SPFA;

这两种算法都用了队列优化,Dijkstra是优先队列,SPFA是普通队列;


Dijkstra

先介绍第一种,也是用的最多的一种最短路算法:Dijkstra;

这种算法的思想就是先根据给定的起点 s ,找到这个点 s 所能连的点,更新一下所能连到的点的路径,然后放入优先队列里面;优先队列维护两个东西,一个是起点 s 到这个点的路径权值,一个是这个点的标号;

这里重点要说的是对于负权边的处理,对于负权边,Dijkstra是没法处理的

比如:
1–2 权值为1
2–3 权值为-3
3–1 权值为2

根据Dijkstra的每个点只遍历一遍,所以1–2的最短路是1,而不是-1;当然保证最短路每条边只走一次;

Dijkstra模板:

struct queue_element
{
    int x,y,dis_value;
    queue_element(int x_,int y_,int dis_value_):
        x(x_),y(y_),dis_value(dis_value_){}
    bool operator < (const queue_element &other) const
    {
        return dis_value>other.dis_value;
    }
};
inline void dijkstra()//可以不带参数,也可以把起点带进来
{
    priority_queue<element> q;//优先队列大法吼
    q.push(element(1,0));//把起点压进去
    while(!q.empty())//不空就说明还有点没搜完
    {
        element k=q.top();//取出队首
        q.pop();
        if(vis[k.node])//如果已经在集合中(被搜到过)
            continue;//扔掉
        vis[k.node]=1;//标记
        dis[k.node]=k.value;//存下最短路(由于优先队列的排序已经相当于完成了松弛,所以这就是答案)
        for(vector<edge>::iterator it=v[k.node].begin();it!=v[k.node].end();++it)//用指针遍历邻接表
            q.push(element(it->node,it->weight+k.value));//松弛
    }
}

SPFA

这里先说一下,除非有负权边和负环要用SPFA,其他一概不用它;

这个算法和 Dijkstra 的区别还是挺大的:

  1. queue而不是priority_queue;
  2. 当一个点出队时,要擦掉它的标记,保证它可以被再次遍历到;
  3. 统计每个点的遍历次数,如果大于等于 n 次,说明有负环;

这里不在深入解释这个算法:

bool SPFA()
{
    queue<int> q;//队列
    memset(dis,127/3,sizeof(dis));//初始化一个很大的数
    dis[s]=0;//原点最短路是0
    q.push(s);//原点入队
    vis[s]=1;//标记入队
    while(!q.empty())//队列不空说明没跑完
    {
        int k=q.front();//取出队首
        q.pop();
        vis[k]=0;//擦去标记
        ++cnt[k];//统计次数
        if(cnt[k]>=n)//如果超过n-1说明有负环
            return 0;//报错
        for(vector<edge>::iterator it=v[k].begin();it!=v[k].end();++it)//邻接表遍历相连的边
            if(dis[it->node]>dis[k]+it->weight)//如果可以松弛
            {
                dis[it->node]=dis[k]+it->weight;//松弛
                if(!vis[it->node])//如果被松弛的点不在队列里
                {
                    vis[it->node]=1;//标记入队
                    q.push(it->node);//入队
                }
            }
    }
    return 1;//顺利完成
}
发布了264 篇原创文章 · 获赞 46 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_44291254/article/details/104901054
今日推荐