题目情境#
题目链接:https://www.luogu.com.cn/problem/B3647 ↗
题目描述
给出一张由 个点 条边组成的无向连通图。
求出所有点对 之间的最短路径。
输入格式
第一行为两个整数 ,分别代表点的个数和边的条数。
接下来 行,每行三个整数 ,代表 之间存在一条边权为 的边。
输出格式
输出 行每行 个整数。
第 行的第 个整数代表从 到 的最短路径。
输入 #1
4 4
1 2 1
2 3 1
3 4 1
4 1 1plaintext输出 #1
0 1 2 1
1 0 1 2
2 1 0 1
1 2 1 0plaintext对于 的数据,,,任意一条边的权值 是正整数且 。
数据中可能存在重边。
算法解析:#

Floyd 是动态规划求全源最短路: 表示只允许经过前 个中间点时 到 的最短路,滚动后即为 。三重循环 ,可处理负权边但不能有负环;也用于求传递闭包。注意 在最外层。
Python代码实现#
def floyd():
for k in range(1, n + 1):
for i in range(1, n + 1):
for j in range(1, n + 1):
d[i][j] = min(d[i][j], d[i][k] + d[k][j])
n, m = map(int, input().split())
d = [[int(1e20) for __ in range(n + 1)] for _ in range(n + 1)]
for i in range(1, n + 1):
d[i][i] = 0
for i in range(m):
a, b, c = map(int, input().split())
d[a][b] = min(d[a][b], c)
floyd()
for i in range(1, n + 1):
print(*d[i][1:])pythonC++代码实现#
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=210,M=20010;
int n,m,a,b,c;
int d[N][N];
void floyd(){
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int main(){
cin>>n>>m;
memset(d,0x3f,sizeof d);
for(int i=1; i<=n; i++)d[i][i]=0;
for(int i=0; i<m; i++){
cin>>a>>b>>c;
d[a][b]=min(d[a][b],c); //重边
}
floyd();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
printf("%d ",d[i][j]);
puts("");
}
return 0;
}c