D04【模板】最短路 Floyd 算法
D04【模板】最短路 Floyd 算法_哔哩哔哩_bilibili
Floyd 算法
是用来求任意两个结点之间的最短路的.
复杂度比较高,但是常数小,容易实现(只有三个 for).
适用于任何图,不管有向无向,边权正负,但是最短路必须存在.(不能有负环)
实现
我们定义一个数组 f[k][x][y],表示只允许经过结点 1
到 𝑘,结点 𝑥
到结点 𝑦
的最短路长度.
很显然,f[n][x][y] 就是结点 𝑥 到结点 𝑦 的最短路长度.
f[0][x][y]:当 𝑥 =𝑦
的时候为零,因为到本身的距离为零;当 𝑥
与 𝑦 没有直接相连的边的时候,为 +∞.
f[k][x][y] = min(f[k-1][x][y],f[k-1][x][k]+f[k-1][k][y])(f[k-1][x][y]为不经过 𝑘
点的最短路径,f[k-1][x][k]+f[k-1][k][y]为经过了 𝑘
点的最短路).
我们可以发现数组的第一维是可以省略的,于是可以直接改成 f[x][y] = min(f[x][y],f[x][k]+f[k][y]).
综上时间复杂度是 𝑂(𝑁3),空间复杂度是 𝑂(𝑁2)
应用
给一个正权无向图,找一个最小权值和的环.
已知一个有向图中任意两点之间是否有连边,要求判断任意两点是否连通.求 图的传递闭包.
// Floyd 算法 O(n^3) #include<bits/stdc++.h> using namespace std; const int N=110; 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]=d[b][a]=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(""); } }
P2910 [USACO08OPEN] Clear And Present Danger S - 洛谷
P2888 [USACO07NOV] Cow Hurdles S - 洛谷
P2935 [USACO09JAN] Best Spot S - 洛谷
浙公网安备 33010602011771号