多源最短路径——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;
}
运行结果: