D04【模板】最短路 Floyd 算法

D04【模板】最短路 Floyd 算法_哔哩哔哩_bilibili

 

最短路 - OI Wiki

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)

应用

给一个正权无向图,找一个最小权值和的环.

已知一个有向图中任意两点之间是否有连边,要求判断任意两点是否连通.求 图的传递闭包

 

B3647 【模板】Floyd - 洛谷

// 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 - 洛谷

 

posted @ 2022-05-28 13:15  董晓  阅读(2110)  评论(2)    收藏  举报