多源最短路径——floyd-Warshall算法的拓展

本文详细介绍了Floyd-Warshall算法的应用于求解多源最短路径问题的方法,包括核心代码解析及如何通过增加路径记录功能获取最短路径的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多源最短路径——floyd-Warshall算法的拓展

关于多源最短路径算法,我看了一下别人的博客——gooddeep的博客
总之核心代码就是五行。
这里写图片描述

for(int k=1;k<5;k++)
    for(int i=1;i<5;i++)
        for(int j=1;j<5;j++)
            if(infor[i][j]>infor[i][k]+infor[k][j])
            infor[i][j]=infor[i][k]+infor[k][j]);

实际上,这个算法遍历整个矩阵,不断地将两地之间可以缩小的距离计算出来,并不断更新,且每一次的更新都是建立在前一次更新的基础上。
例:
对于本次更新的数据:infor[i][j]将更新为infor[i][k] + infor[k][j]
infor[i][k] 与 infor[k][j]又是在上一次的更新中而来。
如此一来,我们最后得到的数据就是遍历了全图后,得到的最短路径的长度。
但是同样,问题来了,我们虽然得到了最短路径的长度,但我们还是不知道路该怎么走。

  • 实际上,最短路径就是将我们经过的节点都记录下来,即多加一行代码,将节点k记录下来。
  • 另外,我们注意到路径每一次更新都是建立在前一次路径更新的基础上的,所以我们需要给矩阵的每一个格都建立一个独立的容器,记录其经过的节点。像这样,所有的容器汇集在一起就好像形成了一个新的矩阵,我们称其为road[][] 路径矩阵。显然这个矩阵会随着infor[][]长度矩阵的更新而更新,最终我们将得到最短路径的所有节点。
  • 路径每一次更新都是建立在前一次路径更新的基础上的,所以有一般情况
    road[i][j]=road[i][k]+k+road[k][j];

    我用的是c++标准库里面的vector容器,实际上用字符串string可能会更简单。
    首先建立一个4*4的指针矩阵,类型为vector。每一个指针都指向一个容器对应一个格的路径。
    对于road[i][j]=road[i][k]+k+road[k][j];的操作即将road[i][k]与k与road[k][j]的对应的容器数据,顺序连接起来,并赋给road[i][j]对应的容器。
    另外在创建一个函数,用于实现road[i][j]=road[i][k]+k+road[k][j];
    注:elc为vector的指针类型的别名

void chear(elc a,elc b,int z,elc c)
 {  
    *a=*b;
    a->push_back(z);

    int csize=c->size();
    for(int i=0;i<csize;i++)
    {
        a->push_back(c->at(i));
     }

 }
实际代码如下
#include<iostream>
#include<vector> 
using namespace std; 
typedef vector<int>* elc;  //为vector<int>的指针类型取个别名elc
#define wx 10000
void printRoad(elc x){
    for(int i=0;i<x->size();i++)
    cout<<x->at(i)<<"->";
}//路径的输出函数
 void chear(elc a,elc b,int z,elc c)
 {  
    *a=*b;
    a->push_back(z);

    int csize=c->size();
    for(int i=0;i<csize;i++)
    {
        a->push_back(c->at(i));
     }

 }//road[i][j]=road[i][k]+k+road[k][j];的实现方式

void print(int *a){
    for(int i=1;i<5;i++)
    {
        for(int j=1;j<5;j++)
        {
                cout<<*(a+i*5+j)<<"  ";
        }   
        cout<<endl;
    }

    return;

}//输出infor数组
int main()
{
    vector<int> *road[5][5];//建立road路径数组,road[0][*]与road[*][0]舍弃不用
    for(int i=1;i<5;i++)
    {
        for(int j=1;j<5;j++)
        {
            road[i][j]=new vector<int>;
        }
    }//为每一个指针开辟一个容器空间,初始为空
    int infor[5][5]={
        0,0,0,0,0,
        0,0,2,6,4,
        0,wx,0,3,wx,
        0,7,wx,0,1,
        0,5,wx,12,0
    };初始infor矩阵
    cout<<"============First=========="<<endl;
    print(infor[0]);
    for(int k=1;k<5;k++)
    {
        for(int i=1;i<5;i++)
        {
            for(int j=1;j<5;j++)
            {
                if(infor[i][j]>infor[i][k]+infor[k][j])
                {
                    infor[i][j]=infor[i][k]+infor[k][j];//更新infor数组
                    chear(road[i][j],road[i][k],k,road[k][j]);//更新路径容器

                }

            }
        }
    }
    cout<<"==========next========"<<endl;
    print(infor[0]);
    for(int i=1;i<5;i++)//将所有路径输出
    {
        for(int j=1;j<5;j++)
        {
                cout<<"==========="<<i<<"->"<<j<<"========"<<endl;
                cout<<"It needs "<<infor[i][j]<<endl;
                cout<<i<<"->";
                    printRoad(road[i][j]);
                    cout<<j<<endl;

        }   
    }



    return 0;
}

运行结果:
这里写图片描述这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fuckguidao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值