算法导论学习笔记(19)——每对顶点间的最短路径(基于Floyd_Warshall算法)
2012-05-07 20:49
411 查看
Floyd-Warshall算法的运行时间为Θ(V3),它同样允许存在负权边,但假设不存在负权回路。该算法考虑的最优子结构与上述描述类似,即最短路径的子路径是最短路径。但是,它对中间路径的范围加以限制,使其增长与最短路径的最大边数的增长同步。令dij(k)=为从顶点i到顶点j、且满足所有中间顶点属于集合{1,2,…,k}的一条最短路径的权值,定义递归解:如果k=0,dij(k)=wij;如果k≥1,dij(k)=min{
dij(k-1), dik(k-1)+ dkj(k-1)}。可以想象,当k=1时,i到j的最短路径或者由边(i,j)构成,或者由边(i,1)、(1,j)构成。当k=2时,i到j的最短路径可能由子路径i到2和子路径2到j构成,而子路径2到j又可能由边(2,1)、(1,j)构成,即k=2的解包含了k=1的解。以此类推,当k=n时,即可得到每对顶点间最短路径的权值。
为了构造最短路径,定义πij(k)为从i出发的一条最短路径上顶点j的前趋,而这条路径上的中间顶点属于集合{1,2,…,k}。定义πij(k)的递归公式,对于k=0,如果i=j或wij=∞,πij(0) =NIT(-1);如果i≠j和wij<∞,πij(0) =i。对于k≥1,如果dij(k-1)≤dik(k-1)+
dkj(k-1),πij(k) =πij(k-1);如果dij(k-1)>dik(k-1)+ dkj(k-1),πij(k) =πkj(k-1)。
完整的实现代码如下:
完整的实现代码如下:
view plaincopy
to clipboardprint?
#include <iostream>
#include <string>
#include <stdio.h>
using
namespace std;
#define MaxVertexNum 100
#define INF 32767
typedef
struct
{
char vertex[MaxVertexNum];
int edges[MaxVertexNum][MaxVertexNum];
int n,e;
}MGraph;
void CreateMGraph(MGraph
&G)
{
int i,j,k,p;
cout<<"请输入顶点数和边数:";
cin>>G.n>>G.e;
cout<<"请输入顶点元素:";
for (i=0;i<G.n;i++)
{
cin>>G.vertex[i];
}
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
G.edges[i][j]=INF;
if (i==j)
{
G.edges[i][j]=0;
}
}
}
for (k=0;k<G.e;k++)
{
cout<<"请输入第"<<k+1<<"条弧头弧尾序号和相应的权值:";
cin>>i>>j>>p;
G.edges[i][j]=p;
}
}
void Dispath(int
A[][MaxVertexNum],int path[][MaxVertexNum],int
n);
void Floyd(MGraph
G)
{
int A[MaxVertexNum][MaxVertexNum],path[MaxVertexNum][MaxVertexNum];
int i,j,k;
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
A[i][j]=G.edges[i][j];
path[i][j]=-1;
}
}
for (k=0;k<G.n;k++)
{
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
if (A[i][j]>A[i][k]+A[k][j])
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
}
}
Dispath(A,path,G.n);
}
void Ppath(int
path[][MaxVertexNum],int i,int
j)
{
int k;
k=path[i][j];
if (k==-1)
{
return;
}
Ppath(path,i,k);
printf("%d",k);
Ppath(path,k,j);
}
void Dispath(int
A[][MaxVertexNum],int path[][MaxVertexNum],int
n)
{
int i,j;
for (i=0;i<n;i++)
{
for (j=0;j<n;j++)
{
if (A[i][j]==INF)
{
if (i!=j)
{
printf("从%d到%d没有路径/n",i,j);
}
}
else
{
printf(" 从%d到%d=>路径长度:%d路径:",i,j,A[i][j]);
printf("%d,",i);
Ppath(path,i,j);
printf("%d/n",j);
}
}
}
}
int main()
{
MGraph G;
CreateMGraph(G);
Floyd(G);
return 0;
}
dij(k-1), dik(k-1)+ dkj(k-1)}。可以想象,当k=1时,i到j的最短路径或者由边(i,j)构成,或者由边(i,1)、(1,j)构成。当k=2时,i到j的最短路径可能由子路径i到2和子路径2到j构成,而子路径2到j又可能由边(2,1)、(1,j)构成,即k=2的解包含了k=1的解。以此类推,当k=n时,即可得到每对顶点间最短路径的权值。
为了构造最短路径,定义πij(k)为从i出发的一条最短路径上顶点j的前趋,而这条路径上的中间顶点属于集合{1,2,…,k}。定义πij(k)的递归公式,对于k=0,如果i=j或wij=∞,πij(0) =NIT(-1);如果i≠j和wij<∞,πij(0) =i。对于k≥1,如果dij(k-1)≤dik(k-1)+
dkj(k-1),πij(k) =πij(k-1);如果dij(k-1)>dik(k-1)+ dkj(k-1),πij(k) =πkj(k-1)。
完整的实现代码如下:
完整的实现代码如下:
view plaincopy
to clipboardprint?
#include <iostream>
#include <string>
#include <stdio.h>
using
namespace std;
#define MaxVertexNum 100
#define INF 32767
typedef
struct
{
char vertex[MaxVertexNum];
int edges[MaxVertexNum][MaxVertexNum];
int n,e;
}MGraph;
void CreateMGraph(MGraph
&G)
{
int i,j,k,p;
cout<<"请输入顶点数和边数:";
cin>>G.n>>G.e;
cout<<"请输入顶点元素:";
for (i=0;i<G.n;i++)
{
cin>>G.vertex[i];
}
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
G.edges[i][j]=INF;
if (i==j)
{
G.edges[i][j]=0;
}
}
}
for (k=0;k<G.e;k++)
{
cout<<"请输入第"<<k+1<<"条弧头弧尾序号和相应的权值:";
cin>>i>>j>>p;
G.edges[i][j]=p;
}
}
void Dispath(int
A[][MaxVertexNum],int path[][MaxVertexNum],int
n);
void Floyd(MGraph
G)
{
int A[MaxVertexNum][MaxVertexNum],path[MaxVertexNum][MaxVertexNum];
int i,j,k;
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
A[i][j]=G.edges[i][j];
path[i][j]=-1;
}
}
for (k=0;k<G.n;k++)
{
for (i=0;i<G.n;i++)
{
for (j=0;j<G.n;j++)
{
if (A[i][j]>A[i][k]+A[k][j])
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
}
}
Dispath(A,path,G.n);
}
void Ppath(int
path[][MaxVertexNum],int i,int
j)
{
int k;
k=path[i][j];
if (k==-1)
{
return;
}
Ppath(path,i,k);
printf("%d",k);
Ppath(path,k,j);
}
void Dispath(int
A[][MaxVertexNum],int path[][MaxVertexNum],int
n)
{
int i,j;
for (i=0;i<n;i++)
{
for (j=0;j<n;j++)
{
if (A[i][j]==INF)
{
if (i!=j)
{
printf("从%d到%d没有路径/n",i,j);
}
}
else
{
printf(" 从%d到%d=>路径长度:%d路径:",i,j,A[i][j]);
printf("%d,",i);
Ppath(path,i,j);
printf("%d/n",j);
}
}
}
}
int main()
{
MGraph G;
CreateMGraph(G);
Floyd(G);
return 0;
}
相关文章推荐
- 算法导论学习笔记(18)——单源最短路径(Dijkstra算法实现)
- 【动态规划】每对顶点之间的最短路径之Floyd-Warshall算法
- 数据结构 学习笔记(八):图(中):最短路径问题(单源最短路径 Dijkstra,多源最短路径 Floyd)
- 所有顶点对之间的最短路径之Floyd-Warshall算法
- hnu12519 Travelling Tom 求所有顶点的最短路径(floyd)
- [Introduction to Algorithms 学习笔记] 单源最短路径
- 最短路径之Dijkstra算法和Floyd-Warshall算法
- 《算法导论》笔记 第24章 24.4 差分约束与最短路径
- Floyd-Warshall算法求任意两点间最短路径
- 最短路径(Floyd_Warshall算法)
- AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)
- 最短路径——迪杰斯特拉算法 学习笔记
- 每对顶点间的最短路径之二——floyd warshall 收藏
- 每对顶点之间的最短路径-Floyd
- 学习笔记---街区最短路径问题算法及优化
- 最短路径算法—Floyd-Warshall算法分析与实现
- 算法导论 - 第25章 每对顶点间的最短路径
- 任意两点之间的最短路径问题(Floyd-Warshall算法)
- hnu12519 Travelling Tom 求所有顶点的最短路径(floyd)
- 数据机构学习笔记(四) 图之单源最短路径Dijkstra算法