最短路径之——Floyd算法(转)

要求有向网中每两个顶点之间的最短距离,用Dijkstra算法的话,只需要将每个顶点都作为一次源点就可以,用Floyd算法的话,虽然在时间复杂度上和Dijkstra算法一样,但是形式上更为简便,整体性更好。下面是代码:

文件"graph.h"

  1 #include<iostream>
2 #include<string>
3 using namespace std;
4
5 const int MAX=99999;
6 const int MAX_VEX_NUM=20;
7 class MGraph
8 {
9 private:
10 string vexs[MAX_VEX_NUM];//顶点数组
11 int arcs[MAX_VEX_NUM][MAX_VEX_NUM];//邻接矩阵
12 int vexnum;//顶点数
13 int arcnum;//边数
14 public:
15 void Create_MG()
16 {
17 int i,j,k;
18 cout<<"输入图的顶点数和边数:";
19 cin>>vexnum>>arcnum;
20 cout<<"输入各个顶点的民称:";
21 for(i=0;i<vexnum;i++)
22 cin>>vexs[i];
23
24 for(i=0;i<vexnum;i++)
25 for(int j=0;j<vexnum;j++)
26 arcs[i][j]=MAX;
27 //上面是初始化邻接矩阵
28
29 for(k=0;k<arcnum;k++)
30 {
31 cout<<"输入每条边对应的始点和终点以及该边的权值:";
32 string v1,v2;
33 int w;
34 cin>>v1>>v2>>w;
35 i=Locate_Vex(v1);
36 j=Locate_Vex(v2);
37
38 while(i<0|| i>vexnum-1 || j<0 || j>vexnum-1)
39 {
40 cout<<"结点位置输入错误,重新输入: ";
41 cin>>v1>>v2>>w;
42 i=Locate_Vex(v1);
43 j=Locate_Vex(v2);
44 }
45
46 arcs[i][j]=w;
47 }
48 cout<<"图构造完成"<<endl;
49 }
50
51 int Locate_Vex(string x) //用于确定顶点在顶点数组中的位置
52 {
53 for(int k=0;vexs[k]!=x;k++);
54 return k;
55 }
56
57 /*------------------------------------------------------------------
58 /
59 / 弗洛伊德(Floyd)算法:求有向网中每两个顶点之间的距离
60 / 第一次,判别(Vi,Vo)和(Vo,Vj),即判断vi->vo->vj路径是否存在,若存在
61 / 则比较vi->vj 和 vi->vo->vj的长度,短的作为vi到vj的之间顶点的序号
62 / 不大于0的最短路径。第二次,再增加一个顶点v1,也就是说,如果(vi,..,v1)
63 / 和(v1,..,vj)分别是当前找到的中间顶点序号不大于0的最短路径,那么
64 / (vi,...,v1,...,vj)就有可能是从vi到vj的中间顶点 不大于1的最短路径。将
65 / 它和已经得到的从vi到vj的中间顶点不大于0的最短路径比较,短的为从vi
66 / 到vj的中间顶点不大于1的最短路径。第三次,在增加一个顶点v2,继续比较。
67 / 依此类推,在经过n次这样的比较之后,最后求得的就是vi到vj的最短路径。
68 /
69 /------------------------------------------------------------------*/
70
71 void Floyd_Short_Path(int path[20][20],int Dist[20][20])
72 {
73 //Dist[v][w]保存从顶点v到w的最短路径长度
74 //path[v][w]保存到达w的前一个顶点
75
76 for(int v=0;v<vexnum;v++)
77 for(int w=0;w<vexnum;w++)
78 {
79 Dist[v][w]=arcs[v][w];
80 if(Dist[v][w]<MAX)
81 path[v][w]=v;
82 else
83 path[v][w]=-1;
84 }
85 for(int u=0;u<vexnum;u++)
86 for(int v=0;v<vexnum;v++)
87 for(int w=0;w<vexnum;w++)
88 if(v!=w && Dist[v][u]+Dist[u][w]<Dist[v][w])
89 {
90 Dist[v][w]=Dist[v][u]+Dist[u][w];
91 path[v][w]=path[u][w];
92 }
93 }
94
95 //下面输出两顶点间最短路径的过程的算法,是利用了path[][]数组的特点,进行逆序输出
96 void Print(int path[20][20],int Dist[20][20])
97 {
98 cout<<"___输出每两个顶点之间的最短路径和经过的顶点___"<<endl;
99 int j,a[10],c;
100 for(int v=0;v<vexnum;v++)
101 for(int w=0;w<vexnum;w++)
102 if(Dist[v][w]<MAX)
103 {
104 cout<<"顶点"<<vexs[v]<<"到顶点"<<vexs[w]<<"的最短路径长为"<<Dist[v][w]<<endl;
105 cout<<"经过的顶点为:";
106 j=w;
107 c=0;
108 while(path[v][j]!=-1)
109 {
110 a[c]=path[v][j];
111 j=path[v][j];
112 c++;
113 }
114 for(j=c-1;j>=0;j--)
115 cout<<vexs[a[j]]<<"->";
116 cout<<vexs[w]<<endl;
117 }
118 }
119 };

  测试文件"main.cpp"

 1 #include"graph.h"
2
3 int main()
4 {
5 MGraph G;
6 G.Create_MG();
7
8 int Dist[20][20];
9 int path[20][20];
10
11 cout<<"求有向网中没两个顶点之间的最短路径"<<endl;
12 G.Floyd_Short_Path(path,Dist);
13 cout<<endl;
14
15 G.Print(path,Dist);
16 cout<<endl;
17
18 return 0;
19 }
20

  下面是输入和输出结果:

 1 输入图的顶点数和边数:6 8
2 输入各个顶点的民称:v1 v2 v3 v4 v5 v6
3 输入每条边对应的始点和终点以及该边的权值:v1 v3 10
4 输入每条边对应的始点和终点以及该边的权值:v1 v5 30
5 输入每条边对应的始点和终点以及该边的权值:v1 v6 100
6 输入每条边对应的始点和终点以及该边的权值:v2 v3 5
7 输入每条边对应的始点和终点以及该边的权值:v3 v4 50
8 输入每条边对应的始点和终点以及该边的权值:v5 v4 20
9 输入每条边对应的始点和终点以及该边的权值:v4 v6 10
10 输入每条边对应的始点和终点以及该边的权值:v5 v6 60
11 图构造完成
12 求有向网中没两个顶点之间的最短路径
13
14 ___输出每两个顶点之间的最短路径和经过的顶点___
15 顶点v1到顶点v3的最短路径长为10
16 经过的顶点为:v1->v3
17 顶点v1到顶点v4的最短路径长为50
18 经过的顶点为:v1->v5->v4
19 顶点v1到顶点v5的最短路径长为30
20 经过的顶点为:v1->v5
21 顶点v1到顶点v6的最短路径长为60
22 经过的顶点为:v1->v5->v4->v6
23 顶点v2到顶点v3的最短路径长为5
24 经过的顶点为:v2->v3
25 顶点v2到顶点v4的最短路径长为55
26 经过的顶点为:v2->v3->v4
27 顶点v2到顶点v6的最短路径长为65
28 经过的顶点为:v2->v3->v4->v6
29 顶点v3到顶点v4的最短路径长为50
30 经过的顶点为:v3->v4
31 顶点v3到顶点v6的最短路径长为60
32 经过的顶点为:v3->v4->v6
33 顶点v4到顶点v6的最短路径长为10
34 经过的顶点为:v4->v6
35 顶点v5到顶点v4的最短路径长为20
36 经过的顶点为:v5->v4
37 顶点v5到顶点v6的最短路径长为30
38 经过的顶点为:v5->v4->v6
39
40 Press any key to continue

  












原文地址:https://www.cnblogs.com/math2010/p/2142063.html