非加权无向图Floyd-Warshall算法优化与改进

 http://yxwang.spaces.live.com/Blog/cns!BD1957499C10CE30!487.entry

 

非加权无向图Floyd-Warshall算法优化与改进最近反复用到图的(两两结点)最短路径长度算法,对于非加权、无向图的邻接矩阵,采用经典的Floyd-Warshall算法似乎效率不高。

在网上找了点资料,Valerio Schiavoni的这篇日志有点帮助。简要摘录过来,并统一了符号,校正了错误。

 

 以下代码中, int a[i][j]表示从结点i到j的最短路径长度, n为结点总数。

--------------------------------------------------------------------------------

经典实现

void computeAPSP(const int n) { /* calculate shortest paths from every vertex to every vertex */ for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { a[i][j] = min( a[i][j], a[i][k] + a[k][j] ); } } } }

 --------------------------------------------------------------------------------

第1次优化: 利用矩阵的对称性

void computeAPSP(const int n) { for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { const int a_ki = a[k][i]; for (int j = 0; j < i; j++) { a[i][j] = min( a[i][j], a_ki + a[k][j] ); a[j][i] = a[i][j]; } } } }

 --------------------------------------------------------------------------------

第2次优化: 只使用矩阵的下三角部分

void computeAPSP(const int n) { for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { if (k != i) { const int a_ki = (k < i) ? a[i][k] : a[k][i]; for (int j = 0; j < min(k, i); j++) a[i][j] = min( a[i][j], a_ki + a[k][j] ); for (int j = k + 1; j < i; j++) a[i][j] = min( a[i][j], a_ki + a[j][k] ); } } } }

 --------------------------------------------------------------------------------

第3次优化: 跳过不存在的路径

void computeAPSP(const int n) { for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { if (k != i) { const int a_ki = (k < i) ? a[i][k] : a[k][i]; // skip if no path if (a_ki == POSITIVE_INFINITY) continue; for (int j = 0; j < min(k, i); j++) a[i][j] = min( a[i][j], a_ki + a[k][j] ); for (int j = k + 1; j < i; j++) a[i][j] = min( a[i][j], a_ki + a[j][k] ); } } } }

--------------------------------------------------------------------------------

第4次优化: 避免大量调用数学函数

void computeAPSP(const int n) { for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { if (k != i) { const int a_ki = (k < i) ? a[i][k] : a[k][i]; // skip if no path if (a_ki == POSITIVE_INFINITY) continue; for (int j = 0; j < min(k, i); j++) { const int s_kj = a_ki + a[k][j]; if( s_kj < a[i][j] ) a[i][j] = s_kj; } for (int j = k + 1; j < i; j++) { const int s_jk = a_ki + a[j][k]; if( s_jk < a[i][j] ) a[i][j] = s_jk; } } } } }

你可能感兴趣的:(非加权无向图Floyd-Warshall算法优化与改进)