【最短路算法】SPFA

引入

在计算机科学的世界里,算法就像是星空中的繁星,各自闪烁着智慧的光芒。它们沉默而坚定,像是一群不语的哲人,默默地解答着世界的问题。

算法的步骤,如同优美的诗行,让复杂的问题在流转的字符中得以释放。它们如同山间清泉,从一座山峰流淌到另一座山峰,涤荡着问题的尘埃,揭示出真实的面貌。

它们像是一把把钥匙,打开了通往计算机科学的大门。我们用它们来解决问题,用它们来创造奇迹。它们是我们智慧的结晶,是我们对世界的理解和对未来的憧憬。

走进这个充满算法的世界,感受那智慧的光芒和诗意的韵律。让我们一起探索未知的领域,寻找那最美的风景和最珍贵的宝藏。

算法不仅是计算机科学的基础,更是我们生活的诗意所在。它们让我们看到了未来的希望,感受到了科技的魅力。所以,让我们一起拥抱算法,让它们为我们的生活增添色彩,为我们的世界带来更多的可能性。

算法就像是计算机科学中的一道道美食佳肴,它们各自拥有独特的味道和风味。有些算法如同细腻的法式甜点,复杂而精致,需要我们耐心地逐一品味;有些算法则如同朴实的乡村面包,简单而实用,让人感到亲切和温暖。

基本介绍

而在这茫茫的算法大海中,有一种算法闪烁着亮丽的光彩——最短路算法。

最短路算法是一种图论算法,用于在加权图中找到两个节点之间的最短路径。这种算法在现实生活中有着广泛的应用,例如:

  1. 交通规划:最短路算法可以用于城市交通规划,帮助确定最短路线,以减少交通拥堵和提高交通效率。
  2. 物流配送:在物流配送中,最短路算法可以帮助确定最短路径,以最小化运输成本和时间。
  3. 网络设计:在计算机网络中,最短路算法可以帮助确定最佳路由,以确保数据包能够以最快的速度传输。
  4. 地理信息系统:在地理信息系统中,最短路算法可以用于确定两点之间的最短路径,例如在地图上查找两点之间的最佳路线。

其中,SPFA是打开图论大门的一个钥匙,就让我们走进它吧。

思路

归根结底,SPFA就是宽搜,看看就懂了。

#include 
using namespace std;
struct edge{int x, y, c, pre;} a[410000];int alen, last[11100];
void ins(int x, int y, int c)//ins函数的功能是建立一条从x出发到y且长度为c的边
{
    a[++alen] = edge{x, y, c, last[x]}; 全局增加一条有向边,并赋值
    last[x] = alen;                     //建立边与边的联系(都是从x出发)
}

int n, m, d[11100]; //d[i]表示目前i和出发点的最短距离
bool v[11100];      //v[i]等于true表示点i在更新队列中,等于false表示点i不在更新队列中
void spfa()
{
    memset(d, 63, sizeof(d));d[1] = 0; //初始化d数组,出发点为1,出发点到自己的距离为0
    memset(v, 0, sizeof(v)); v[1] = 1; //初始化v数组,v[1]等于1,表示出发点1进入队列
    deque Q; Q.push_back(1);   //定义更新队列,出发点进入更新队列
    while (!Q.empty()) //只要队列不为空,就表示还有点等着更新别的点
    {
        int x = Q.front();                     //从队列中取出准备好更新别的点的点x
        for (int k = last[x]; k; k = a[k].pre) //重点理解!k首相等于和x相连的最后一条边的编号。那么倒数第二条和x相连的边的编号是多少呢?在a[k].next可以找到
        {
            int y = a[k].y;
            if (d[y] > d[x] + a[k].c) //尝试用x的最短距离更新y的最短距离
            {
                d[y] = d[x] + a[k].c; //如果点被更新了,那么它马上有冲动(想进更新队列)要去更新它的"亲朋好友"(与之直接相连的点)
                if (v[y] == 0)        //如果点y不在队列,则进入队列;如果已经在队列了,则不用再进入。
                {
                    Q.push_back(y);
                    v[y] = 1;
                }
            }
        }
        Q.pop_front(); //此时x已经更新完它的"亲朋好友",完成使命,退出队列Q
        v[x] = 0;      //标记x已经不再队列,以后x有可能会再次进入队列
    }
    //队列没有点等着更新别的点了,那么意味着所有点的d值都是最优的
    if (d[n] == d[0]) printf("-1\n"); //d[0]为初始的最大值,d[n]等于d[0]表示点n没有被更新,即点n无法到达。
    else              printf("%d", d[n]);
}
int main()
{
    scanf("%d%d", &n, &m);
    alen = 0;
    memset(last, 0, sizeof(last)); //注意构图之前一定要初始化,不然后果很严重!
    for (int i = 1; i <= m; i++)
    {
        int x, y, c;
        scanf("%d%d%d", &x, &y, &c); //题目给出的是无向边,而我们的边目录是有向边
        ins(x, y, c);
        ins(y, x, c); //建立正向边、反向边
    }
    spfa();
    return 0;
}

详细注释都写在代码里面了,好好看。

例题 

不放了,上洛谷自己查吧.

【最短路算法】SPFA_第1张图片

 据说,一个欠揍的行为,需要一张图来安慰。

你可能感兴趣的:(图论,算法,图论,c++)