就拿从1到3,可以直接1->3,也可以1->2->3,我们发现,通过一个“中转”的2,1->3路径会变短。
可以在一个路径中插入另一个顶点,这样可能会比直接过去的路径更短,假设每个顶点都经过顶点2中转,可以有这样的语句。
我们用二维数组graph[][]存储图
int i;
int j;
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
if(graph[i][j]>graph[i][2]+graph[2][j])//通过中转路径变短了
graph[i][j]=graph[i][2]+graph[2][j];//则将从i到j的路径长度改为中转后的较短路径
}
}
中转顶点可以是图中的任意一个顶点,所以将所有顶点做一次中转顶点 即可以将用一个循环变量来当作中转点
int i;
int j;
int k;
for(k=1;k<=n;++k){
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
if(graph[i][j]>graph[i][2]+graph[2][j])//通过中转路径变短了
graph[i][j]=graph[i][2]+graph[2][j];//则将从i到j的路径长度改为中转后的较短路径
}
}
}
完整代码如下:
#include
const int INF=999999999;
int main(void){
int graph[10][10];
int n,m;//n个顶点,m条边
printf("请输入定点数与边数:");
scanf("%d%d",&n,&m);
//初始化二维数组
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
graph[i][j]=INF;
}
graph[i][i]=0;
}
for(int i=1;i<=m;++i){
int s,e;
printf("第%d条边及其权值:",i );
scanf("%d%d",&s,&e);
scanf("%d",&graph[s][e]);
}
/*********核心部分*********/
int i,j,k;
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
for(k=1;k<=n;++k){
if(graph[j][i]!=INF && graph[i][k]!=INF && graph[j][i]+graph[i][k]%d %d\n",i,j,graph[i][j]);
}
return 0;
}
虽然用插一个中转点来引出这段代码,但是最短路径不一定全是只会有一个中转点。
举个栗子:假设一个最短路径是1->3->5->7,上述算法先找出从1到5的最短路径是1->3->5,现在的graph[1][5]被更新成为了grap[1][3]+graph[3][5],接下来计算1->7的最短路径时上述算法算出的时1->5->7,这里的1->5实际上是1->3->5。这样说可能有点乱,希望的对理解这个算法有点帮助。