问题描述
Input
第一行四个数为n,m,n表示顶点个数,m表示边的条数。
接下来m行,每一行有三个数t1、t2 和t3,表示顶点t1到顶点t2的路程是t3。请注意这些t1->t2是单向的。Output
输出一个n*n的矩阵,第n行第n列表示定点n到n的距离。每一行两个数间由空格隔开Sample Input
5 8
1 2 2
2 3 3
3 4 4
4 5 5
5 3 3
3 1 4
2 5 7
1 5 10Sample Output
0 2 5 9 9
7 0 3 7 7
4 6 0 4 9
12 14 8 0 5
7 9 3 7 0More Info
输出结果每行的最后一个数字后不需要留空格哦~
算法思想
当任意两点之间不允许经过第三个点时,这些城市之间最短路程就是初始路程。
假如现在只允许经过1号顶点,求任意两点之间的最短路程,应该如何求呢?只需判断e[i][1]+e[1][j]是否比e[i][j]要小即可。e[i][j]表示的是从i号顶点到j号顶点之间的路程。e[i][1]+e[1][j]表示的是从i号顶点先到1号顶点,再从1号顶点到j号顶点的路程之和。其中i是1~n循环,j也是1~n循环,代码实现如下
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if ( e[i][j] > e[i][1]+e[1][j] )
e[i][j] = e[i][1]+e[1][j];
}
}
当只允许经过两个顶点时的代码如下:
//经过1号顶点
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if (e[i][j] > e[i][1]+e[1][j]) e[i][j]=e[i][1]+e[1][j];
//经过2号顶点
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if (e[i][j] > e[i][2]+e[2][j]) e[i][j]=e[i][2]+e[2][j];
核心代码只有五行:
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
一句话来概括就是:最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。
- i 出发城市
- j 到达城市
- k 中转城市
全部代码
#include <iostream>
using namespace std;
int main()
{
int datas[105][105];
int n,m;
int t1,t2,t3;
const int inf = 99999;
cin >> n >> m;
// 初始化矩阵
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j){
datas[i][j] = 0;
}else{
datas[i][j] = inf;
}
}
}
// 输入边
for(int i=1;i<=m;i++){
cin >> t1 >> t2 >> t3;
datas[t1][t2] = t3;
}
// 核心算法
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(datas[i][j] > datas[i][k] + datas[k][j]){
datas[i][j] = datas[i][k] + datas[k][j];
}
}
}
}
// 打印结果
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(j!=n)
cout << datas[i][j] << " ";
else
cout << datas[i][j] << endl;
}
}
return 0;
}
来源:CSDN
作者:Hello King
链接:https://blog.csdn.net/qq_43497702/article/details/103992746