图论-最短路Floyd算法
文章目录
- Floyd(弗洛依德)算法
- 路径记录与输出
Floyd(弗洛依德)算法
是动态规划算法,也称插点法。是全源最短路算法。
状态表示
d[k,i,j]
表示从i到j,且中间只经过节点编号1~k的最短路径的长度。
状态计算
路径的选择分两种:
- 1.路径不经过k点,继承原值:
d[k,i,j]=d[k-1,i,j]
- 2.路径经过k点,松弛操作:
d[k,i,j]=d[k-1,i,k]+d[k-1,k,j]
代码展示
void fioyd()
{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]);}}}
}
!!!
K一定要在最外层
k放在内层会出错。
因为该算法是通过递归,必须将k-1层的所有状态计算出来后才能得到第k层的值。
不管路径经不经过k点,计算都与k无关,可以省去第一维。
初始化时:
- 如果i,j两点间无边直接相连,d[i][j]初始化为无穷大。
- 如果有边,d[i][j]就是二者边权。
- i=j,自身到自身的距离为0,d[i][j]=0。
枚举完n层后,所有的最短路都会被找出来了。
路径记录与输出
void path(int x,int y)
{if(p[x][y]==0)return ;int k=p[x][y];//x.y之间的最短路path(x,k);cout<<k<<" ";path(k,y); }
完整代码
int d[N][N],p[N][N];
void fioyd()
{for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(d[i][j]>d[i][k]+d[k][j]){d[i][j]=d[i][k]+d[k][j];p[i][j]=k; }}}}
}
void path(int x,int y)
{if(p[x][y]==0)return ;int k=p[x][y];path(x,k);cout<<k<<" ";path(k,y); }
floyd(){cin>>a>>b;cout<<a<<" ";path(a,b);cout<<b<<" ";}
时间复杂度:O(n3n^3n3)