蒟蒻第一次发博文,有误还请指出
正文开始
总的来说,Floyd算法是种求图中最短路的算法(废话)
我们假设有向图中存在n个节点,m条有向路径,编号为u的点到编号为v的点的距离为dis[u][v]
如果两个节点之间没有直接的路径,则距离设为无穷大
我们使用三层循环来遍历所有节点,通过比较当前节点经过中间节点到达另一个节点的距离和直接到达另一个节点的距离的大小来更新最短距离
示意图:
整个算法完成后,相邻的两个节点总是最短路径
具体实例如下:
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f//传统无穷大
using namespace std;
const int N=205;
int n,m,dis[N][N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
memset(dis,0x3f,sizeof dis);//赋值为inf
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
dis[u][v]=min(dis[u][v],w);//重边保留最短的一条
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
//dis[i][j]表示直接由i节点到达j节点的距离,dis[i][k]+dis[k][j]表示由i节点经过k节点再到j节点的距离
int u,v;
cin>>u>>v;
if(dis[u][v]>0&&dis[u][v]!=0x3f3f3f3f)cout<<dis[u][v];
else cout<<"impossible";//无直接路径
return 0;
}
//时间复杂度O(n^3)
常见疑问
k循环为什么要放在最外层?
在循环中,k表示从i→j所经过的中间节点,将k循环放在最外层是为了确保在每次更新节点之间的最短距离时,我们已经考虑了所有可能经过的中间节点
图中是否出现负权回路该如何判断?
常见的判断方法是在算法的基础上增加一个额外的步骤:在循环结束后遍历所有节点,检查是否存在某个节点到自身的最短路长为负数。如果存在,则说明图中存在负权回路
另一种方法则是在算法中设置一个最大迭代次数,当迭代次数超过阈值时,即使算法还没有收敛,也停止迭代并判断存在负权回路。这样可以避免陷入死循环,同时也能够及时判断负权回路的存在