Floyd算法学习笔记
Floyd算法
这是最简单 码量最低 最无脑我们学的第一个最短路径算法。
他的本质其实是动态规划。万恶的
要想求任意两点最短路,我们就要把它存储起来(废话),由于 f[i][j]
表示距离,否则初始化为无穷大,比如 2147483648 0x3f3f3f3f 之类的。
方法
核心就是“三角不等式”——也就是说,如果绕路要比直接走近,那么就绕路。注意,这里的直接走并不仅仅是指走直线,它也可能是绕路更新以后变成当前的“直线”距离的。
那么,具体我们应该怎样实现呢?必须遵循一定的规律。考虑到
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]);
因此,这种算法的时间复杂度为
-
求出的是任意两点间的最短路。 和某种死了的算法都只能求出“单源最短路”。 -
的一个性质是“传递闭包”。在解决某些看似与最短路毫无关系的问题时,这个性质却经常有很大的用处。
模板代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N];
int n,m;
int main(){
cin>>n>>m;
memset(a,0x3f,sizeof(a));
for(int i=1;i<=n;i++)a[i][i]=0;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
a[u][v]=a[v][u]=min(a[u][v],w);
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) cout<<a[i][j]<<" ";
cout<<endl;
}
}
应用 1:传递闭包
比较常见的例子有P1037 [NOIP2002 普及组] 产生数。
这个题让人一眼就想到了
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=a[i][j]||(a[i][k]&&a[k][j]);
}
}
}
这样我们就能找到每一个数的变化方式,最后根据乘法原理,把他们都乘起来就可以了。代码:
点击查看代码
#include<bits/stdc++.h>
#define very_long __uint128_t
using namespace std;
const int N=110;
bool a[N][N];
int s[N];
void put_vl(__uint128_t a){
if(a>9) put_vl(a/10);
putchar(a%10+'0');
}
int wei(int x){
int tot=0;
do{
tot++;
}while(x=x/10);
}
unsigned long long int m;
very_long ans=1;
string n;
int main(){
cin>>n>>m;
memset(a,0,sizeof(a));
for(int i=0;i<=9;i++)a[i][i]=1;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
a[u][v]=1;
}
for(int k=0;k<=9;k++){
for(int i=0;i<=9;i++){
for(int j=0;j<=9;j++){
a[i][j]=(a[i][k]&&a[k][j])||a[i][j];
}
}
}
for(int i=0;i<=9;i++){
for(int j=0;j<=9;j++)s[i]+=a[i][j];
}
int cnt=n.size();
while(cnt--)ans*=s[n[cnt]-'0'];
put_vl(ans);
}
(__uint128_t
是一种非常大的整数。由于积可能很大,必须用uint128
或者是干脆用高精度)
应用 2:k条边的最短路
有些时候,我们希望找到一条最短路径,但是我们有些时候需要找到的是要“经过 c
,c[k][i][j]
表示经过
点击查看代码
#include<bits/stdc++.h>
using namespace std;
struct matrix{
int x[201][201];
}d;
int n,t,s,e;
bool vis[1001];
int nm[1001],tot;
matrix operator *(matrix A,matrix B){
matrix C;
memset(C.x,0x3f,sizeof(C.x));
for(int k=0;k<tot;k++)
for(int i=0;i<tot;i++)
for(int j=0;j<tot;j++) C.x[i][j]=min(A.x[i][k]+B.x[k][j],C.x[i][j]);
return C;
}
matrix Fast(matrix A,long long n){
matrix S=A;
n--;
while(n){
if(n&1){
S=S*A;
}
A=A*A;
n=n>>1;
}
return S;
}
int main(){
cin>>n>>t>>s>>e;
memset(d.x,0x3f,sizeof(d.x));
for(int i=0;i<t;i++){
int u,v,w;
cin>>w>>u>>v;
if(!vis[u])vis[u]=1,nm[u]=tot++;
if(!vis[v])vis[v]=1,nm[v]=tot++;
d.x[nm[u]][nm[v]]=d.x[nm[v]][nm[u]]=w;
}
d=Fast(d,n);
cout<<d.x[nm[s]][nm[e]]<<endl;
}
本文作者:liyuanzhuo6811
本文链接:https://www.cnblogs.com/liyuanzhuo6811/p/18030942/floyd-learn-bi-ji
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步