Floyd-Warshall算法实现类

图的最短路径算法就剩下几个了,Floyd-Warshall算法是利用动态规划来实现的,其可以用来统计图的任意点对之间的距离。不过复杂度显而易见,需要O(V^3)。

Wiki上有该算法的原理如下:

D_{i,j,k}为从ij的只以(1..k)集合中的节点为中间节点的最短路径的长度。

  1. 若最短路径经过点k,则D_{i,j,k}=D_{i,k,k-1}+D_{k,j,k-1}
  2. 若最短路径不经过点k,则D_{i,j,k}=D_{i,j,k-1}

因此,D_{i,j,k}=\mbox{min}(D_{i,k,k-1}+D_{k,j,k-1},D_{i,j,k-1})

顶点对之间的最短路径是指:对于给定的有向网G=(V,E),要对G中任意一对顶点有序对V、W(V≠W),找出V到W的最短距离和W到V的最短距离。

    解决此问题的一个有效方法是:轮流以每一个顶点为源点,重复执行迪杰斯特拉算法n次,即可求得每一对顶点之间的最短路径,总的时间复杂度为O(n3)。

弗洛伊德(Floyd)提出了另外一个求图中任意两顶点之间最短路径的算法,虽然其时间复杂度也是 O(n3),但其算法的形式更简单,易于理解和编程。

算法基本思想

弗洛伊德算法仍然使用图的邻接矩阵arcs[n+1][n+1]来存储带权有向图。算法的基本思想是:设置一个n x n的矩阵A(k),其中除对角线的元素都等于0外,其它元素a(k)[i][j]表示顶点i到顶点j的路径长度,K表示运算步骤。开始时,以任意两个顶点之间的有向边的权值作为路径长度,没有有向边时,路径长度为∞,当K=0时, A (0)[i][j]=arcs[i][j],以后逐步尝试在原路径中加入其它顶点作为中间顶点,如果增加中间顶点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路径,修改矩阵元素。具体做法为:  

第一步,让所有边上加入中间顶点1,取A[i][j]与A[i][1]+A[1][j]中较小的值作A[i][j]的值,完成后得到A(1),

第二步,让所有边上加入中间顶点2,取A[i][j]与A[i][2]+A[2][j]中较小的值,完成后得到A(2)…,如此进行下去,当第n步完成后,得到A(n),A(n)即为我们所求结果,A(n)[i][j]表示顶点i到顶点j的最短距离。    

因此,弗洛伊德算法可以描述为:

       A(0)[i][j]=arcs[i][j];               //arcs为图的邻接矩阵

       A(k)[i][j]=min{A(k-1) [i][j],A(k-1) [i][k]+A(k-1) [k][j]}

其中 k=1,2,…,n

定义一个n阶方阵序列:

           D(-1), D(0), …, D(n-1).

   其中 D(-1) [i][j] = G.arcs[i][j];

             D(k) [i][j] = min { D(k-1)[i][j],D(k-1)[i][k] + D(k-1)[k][j] }, k = 0,1,…, n-1

   D(0) [i][j]是从顶点vi 到vj , 中间顶点是v0的最短路径的长度,   

   D(k) [i][j]是从顶点vi 到vj , 中间顶点的序号不大于k的最短路径长度,

   D(n-1)[i][j]是从顶点vi 到vj 的最短路径长度。


代码如下:

  1. #include <iostream>  
  2.   
  3. #define GRAPHSIZE 12  
  4. #define MAX_INT 0x7FFFFFFF  
  5. #define NO_PAHT -1  
  6.   
  7. using namespace std;  
  8.   
  9. class Graph  
  10. {  
  11. public:  
  12.     long map[GRAPHSIZE][GRAPHSIZE];  
  13.     void floydWarshall();  
  14.   
  15.     void getData();  
  16.     void putResult();  
  17.   
  18. private:  
  19.     int vertexNum;  
  20.     int path[GRAPHSIZE][GRAPHSIZE];                 //path[i][j] means the last but one vertex in the shortest path from i to j.  
  21.     long distance[GRAPHSIZE][GRAPHSIZE][GRAPHSIZE]; //distance[i][j][k] means the cost of the shortest path, which has no vertex more than k between.  
  22.   
  23.     void initialize();  
  24.     void putPath(int source, int destination);  
  25. };  
  26.   
  27. void Graph::getData()  
  28. {  
  29.     cout << "Please input the vertex number, no more than " << GRAPHSIZE - 1 << ": ";  
  30.     cin >> vertexNum;  
  31.     cout << "Please input edge number: ";  
  32.     int edgenum;  
  33.     int source, destination,cost;  
  34.     cin >> edgenum;  
  35.     while (edgenum--)  
  36.     {  
  37.         cin >> source >> destination >> cost;  
  38.         map[source][destination] = cost;  
  39.     }  
  40. }  
  41.   
  42. void Graph::putPath(int source, int destination)  
  43. {  
  44.     if (source == destination)  
  45.     {  
  46.         cout << source;  
  47.     }  
  48.     else if (NO_PAHT == path[source][destination])  
  49.     {  
  50.         cout << source << " " << destination << " ";  
  51.     }   
  52.     else  
  53.     {  
  54.         putPath(source, path[source][destination]);  
  55.         cout << destination << " ";  
  56.     }  
  57. }  
  58.   
  59. void Graph::putResult()  
  60. {  
  61.     int shortest;  
  62.     for (int i = 0; i < vertexNum; i++)  
  63.     {  
  64.         for (int j = 0; j < vertexNum; j++)  
  65.         {  
  66.             cout << "From vertex_" << i << " to vertex_" << j << " is: ";  
  67.             shortest = distance[i][j][0];  
  68.             for (int k = 1; k <= vertexNum; k++)  
  69.             {  
  70.                 if (shortest > distance[i][j][k])  
  71.                 {  
  72.                     shortest = distance[i][j][k];  
  73.                 }  
  74.             }  
  75.             if (shortest == MAX_INT)  
  76.             {  
  77.                 cout << "+∞" << endl;  
  78.             }  
  79.             else  
  80.             {  
  81.                 cout << shortest << " Path: ";  
  82.                 putPath(i, j);  
  83.                 cout << endl;  
  84.             }  
  85.         }  
  86.     }  
  87. }  
  88.   
  89. void Graph::initialize()  
  90. {  
  91.     for (int i = 0; i < GRAPHSIZE; i++)  
  92.     {  
  93.         for (int j = 0; j < GRAPHSIZE; j++)  
  94.         {  
  95.             for (int k = 0; k < GRAPHSIZE; k++)  
  96.             {  
  97.                 distance[i][j][k] = MAX_INT;  
  98.             }  
  99.               
  100.             map[i][j] = MAX_INT;  
  101.             if (i == j)  
  102.             {  
  103.                 map[i][j] = 0;  
  104.             }  
  105.   
  106.             path[i][j] = NO_PAHT;  
  107.         }  
  108.     }  
  109.   
  110.     getData();  
  111.   
  112.     for (int i = 0; i < GRAPHSIZE; i++)  
  113.     {  
  114.         for (int j = 0; j < GRAPHSIZE; j++)  
  115.         {  
  116.             distance[i][j][0] = map[i][j];  
  117.         }  
  118.     }  
  119.   
  120. }  
  121.   
  122. void Graph::floydWarshall()  
  123. {  
  124.     initialize();  
  125.   
  126.     int k, i, j;  
  127.     for (k = 1; k < vertexNum; k++)  
  128.     {  
  129.         for (i = 0; i < vertexNum; i++)  
  130.         {  
  131.             for (j = 0; j < vertexNum; j++)  
  132.             {  
  133.                 distance[i][j][k] = distance[i][j][k - 1];  
  134.                 if (distance[i][k][k - 1] != MAX_INT && distance[k][j][k - 1] != MAX_INT && distance[i][j][k] > distance[i][k][k - 1] + distance[k][j][k - 1])  
  135.                 {  
  136.                     distance[i][j][k] = distance[i][k][k - 1] + distance[k][j][k - 1];  
  137.                     path[i][j] = k;  
  138.                 }  
  139.             }  
  140.         }  
  141.     }  
  142. }  
  143.   
  144. int main()  
  145. {  
  146.     Graph test;  
  147.   
  148.     test.floydWarshall();  
  149.     test.putResult();  
  150.   
  151.     return 0;  
  152. }  


其实,也说到了,可以进行优化,空间上的优化。既是在原来的空间上进行迭代,将空间优化为二维,如下:


代码如下:

  1. #include <iostream>  
  2.   
  3. #define GRAPHSIZE 12  
  4. #define MAX_INT 0x7FFFFFFF  
  5. #define NO_PAHT -1  
  6.   
  7. using namespace std;  
  8.   
  9. class Graph  
  10. {  
  11. public:  
  12.     long map[GRAPHSIZE][GRAPHSIZE];  
  13.     void floydWarshall();  
  14.   
  15.     void getData();  
  16.     void putResult();  
  17.   
  18. private:  
  19.     int vertexNum;  
  20.     int path[GRAPHSIZE][GRAPHSIZE];                 //path[i][j] means the last but one vertex in the shortest path from i to j.  
  21.     long distance[GRAPHSIZE][GRAPHSIZE];            //distance[i][j] means the cost of the shortest path from i to j.  
  22.   
  23.     void initialize();  
  24.     void putPath(int source, int destination);  
  25. };  
  26.   
  27. void Graph::getData()  
  28. {  
  29.     cout << "Please input the vertex number, no more than " << GRAPHSIZE - 1 << ": ";  
  30.     cin >> vertexNum;  
  31.     cout << "Please input edge number: ";  
  32.     int edgenum;  
  33.     int source, destination,cost;  
  34.     cin >> edgenum;  
  35.     while (edgenum--)  
  36.     {  
  37.         cin >> source >> destination >> cost;  
  38.         map[source][destination] = cost;  
  39.     }  
  40. }  
  41.   
  42. void Graph::putPath(int source, int destination)  
  43. {  
  44.     if (source == destination)  
  45.     {  
  46.         cout << source;  
  47.     }  
  48.     else if (NO_PAHT == path[source][destination])  
  49.     {  
  50.         cout << source << " " << destination << " ";  
  51.     }   
  52.     else  
  53.     {  
  54.         putPath(source, path[source][destination]);  
  55.         cout << destination << " ";  
  56.     }  
  57. }  
  58.   
  59. void Graph::putResult()  
  60. {  
  61.     int shortest;  
  62.     for (int i = 0; i < vertexNum; i++)  
  63.     {  
  64.         for (int j = 0; j < vertexNum; j++)  
  65.         {  
  66.             cout << "From vertex_" << i << " to vertex_" << j << " is: ";  
  67.   
  68.             shortest = distance[i][j];  
  69.   
  70.             if (shortest == MAX_INT)  
  71.             {  
  72.                 cout << "+∞" << endl;  
  73.             }  
  74.             else  
  75.             {  
  76.                 cout << shortest << " Path: ";  
  77.                 putPath(i, j);  
  78.                 cout << endl;  
  79.             }  
  80.         }  
  81.     }  
  82. }  
  83.   
  84. void Graph::initialize()  
  85. {  
  86.     for (int i = 0; i < GRAPHSIZE; i++)  
  87.     {  
  88.         for (int j = 0; j < GRAPHSIZE; j++)  
  89.         {  
  90.             distance[i][j] = MAX_INT;  
  91.   
  92.             map[i][j] = MAX_INT;  
  93.             if (i == j)  
  94.             {  
  95.                 map[i][j] = 0;  
  96.             }  
  97.   
  98.             path[i][j] = NO_PAHT;  
  99.         }  
  100.     }  
  101.   
  102.     getData();  
  103.   
  104.     for (int i = 0; i < GRAPHSIZE; i++)  
  105.     {  
  106.         for (int j = 0; j < GRAPHSIZE; j++)  
  107.         {  
  108.             distance[i][j] = map[i][j];  
  109.         }  
  110.     }  
  111.   
  112. }  
  113.   
  114. void Graph::floydWarshall()  
  115. {  
  116.     initialize();  
  117.   
  118.     int k, i, j;  
  119.     for (k = 1; k < vertexNum; k++)  
  120.     {  
  121.         for (i = 0; i < vertexNum; i++)  
  122.         {  
  123.             for (j = 0; j < vertexNum; j++)  
  124.             {  
  125.                 if (distance[i][k] != MAX_INT && distance[k][j] != MAX_INT && distance[i][j] > distance[i][k] + distance[k][j])  
  126.                 {  
  127.                     distance[i][j] = distance[i][k] + distance[k][j];  
  128.                     path[i][j] = k;  
  129.                 }  
  130.             }  
  131.         }  
  132.     }  
  133. }  
  134.   
  135. int main()  
  136. {  
  137.     Graph test;  
  138.   
  139.     test.floydWarshall();  
  140.     test.putResult();  
  141.   
  142.     return 0;  

  143. 转载于:http://blog.csdn.net/betabin/article/details/7385663
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值