【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?...
簡介
Floyd-Warshall算法(Floyd-Warshall algorithm),是一種利用動態(tài)規(guī)劃的思想尋找給定的加權(quán)圖中多源點(diǎn)之間最短路徑的算法,與Dijkstra算法類似。該算法名稱以創(chuàng)始人之一、1978年圖靈獎獲得者、斯坦福大學(xué)計算機(jī)科學(xué)系教授羅伯特·弗洛伊德命名。簡單的說就是解決任意兩點(diǎn)間的最短路徑的一種算法,可以正確處理有向圖或負(fù)權(quán)的最短路徑問題,同時也被用于計算有向圖的傳遞閉包。Floyd-Warshall算法的時間復(fù)雜度為O(N3),空間復(fù)雜度為O(N2)。
解決最短路徑問題有幾個出名的算法:
1.dijkstra算法,最經(jīng)典的單源最短路徑算法
2.bellman-ford算法,允許負(fù)權(quán)邊的單源最短路徑算法
3.spfa,其實(shí)是bellman-ford+隊(duì)列優(yōu)化,其實(shí)和bfs的關(guān)系更密一點(diǎn)
4.floyd算法,經(jīng)典的多源最短路徑算法
今天先說說Floyd
Floyd算法詳解
描述
a)如圖:存在【0,1,2,3】 4個點(diǎn),兩點(diǎn)之間的距離就是邊上的數(shù)字,如果兩點(diǎn)之間,沒有邊相連,則無法到達(dá),為無窮大。?
b)要讓任意兩點(diǎn)(例如從頂點(diǎn)a點(diǎn)到頂點(diǎn)b)之間的路程變短,只能引入第三個點(diǎn)(頂點(diǎn)k),并通過這個頂點(diǎn)k中轉(zhuǎn)即a->k->b,才可能縮短原來從頂點(diǎn)a點(diǎn)到頂點(diǎn)b的路程。那么這個中轉(zhuǎn)的頂點(diǎn)k是0~n中的哪個點(diǎn)呢?
算法過程
準(zhǔn)備
1)如圖 0->1距離為5,0->2不可達(dá),距離為∞,0->3距離為7……依次可將圖轉(zhuǎn)化為鄰接矩陣(主對角線,也就是自身到自身,我們規(guī)定距離為0,不可達(dá)為無窮大),如圖矩陣 用于存放任意一對頂點(diǎn)之間的最短路徑權(quán)值。
2)再創(chuàng)建一個二維數(shù)組Path路徑數(shù)組,用于存放任意一對頂點(diǎn)之間的最短路徑。每個單元格的內(nèi)容表示從i點(diǎn)到j(luò)點(diǎn)途經(jīng)的頂點(diǎn)。(初始還未開始查找,默認(rèn)-1)
開始查找
1)列舉所有的路徑(自己到自己不算)
即為:
0 -> 1 , 0 -> 2 , 0 -> 3 ,
1 -> 0 , 1 -> 2 , 1 -> 3 ,
2 -> 0 , 1 -> 1 , 1 -> 3
轉(zhuǎn)化成二元數(shù)組即為:
{0,1},{0,2},{0,3},{1,0},{1,2},{1,3},{2,0},{2,1},{2,3},{3,0},{3,1},{3,2}
2)選擇編號為0的點(diǎn)為中間點(diǎn)
{0,1},{0,2},{0,3},{1,0},{1,2},{1,3},{2,0},{2,1},{2,3},{3,0},{3,1},{3,2}
從上面中二元組集合的第一個元素開始,循環(huán)執(zhí)行以下過程:
{0,1}按照此過程執(zhí)行之后,
0->0 + 0->1的距離不小于0->1 ,下一組{0,2},{0,3}, {1,0},{2,0},{3,0}也同理。
{1,2}按照此過程執(zhí)行,A[1,0] 無窮大, A[0,2]也是無窮大,而A[1,4] = 4,則1點(diǎn)到2點(diǎn)肯定不會從0點(diǎn)中轉(zhuǎn)。
A[1][0]無窮大同理下一組{1,2}, {1,3}也同理。
{2,1}按照此過程執(zhí)行,A[2][0] = 3 ,A[0][1]=5 ,A[2][1] = 3那么 A[2][0]+ ,A[0][1] > A[2][1]
…………
依次類推,遍歷二元組集合,沒有0點(diǎn)適合做中轉(zhuǎn)的
3)選擇編號為1的點(diǎn)為中間點(diǎn)
4)選擇編號為2的點(diǎn)為中間點(diǎn)
依次類推,遍歷二元組集合{0,1},{0,2},{0,3},{1,0},{1,2},{1,3},{2,0},{2,1},{2,3},{3,0},{3,1},{3,2}
,當(dāng)遍歷{3,0}時,A[3][2] = 1 ,A[2][0]=3 ,A[3][0] = 不可達(dá),那么 2點(diǎn)適合做從3點(diǎn)到0點(diǎn)之間的中轉(zhuǎn)點(diǎn)。
設(shè)置距離矩陣A[3][0] = 1+3 =4 ,Path矩陣Path[3][0] = 2點(diǎn),表示從3到0在2點(diǎn)中轉(zhuǎn),距離最近。
如圖表示(紅色單元格),從3到0,最近距離為4,在2點(diǎn)中轉(zhuǎn) 。
依次類推,遍歷完二元組集合
5)選擇編號為3的點(diǎn)為中間點(diǎn),最終結(jié)果
依次類推,遍歷二元組集合,直到所有的頂點(diǎn)都做過一次中間點(diǎn)為止。
6)根據(jù)最終結(jié)果,就可以知道任意2點(diǎn)的最短距離和路徑
比如1點(diǎn)到2點(diǎn)怎么走?根據(jù)路徑Path矩陣,Path[1][2] = 3,表示從點(diǎn)3中轉(zhuǎn),即 1-> 3 ->2
6)如果中轉(zhuǎn)點(diǎn)不止1個呢?
有時候不只通過一個點(diǎn),而是經(jīng)過兩個點(diǎn)或者更多點(diǎn)中轉(zhuǎn)會更短,即a->k1->k2b->或者a->k1->k2…->k->i…->b。
比如頂點(diǎn)1到頂點(diǎn)0,我們看數(shù)組Path
Path[1][0] = 3,說明頂點(diǎn)3是中轉(zhuǎn)點(diǎn),那么再從3到0
Path[3][0] = 2,說明從3到0,頂點(diǎn)2是中轉(zhuǎn)點(diǎn),然后在從2到0
Path[2][0] = -1,說明頂點(diǎn)2到頂點(diǎn)0沒有途徑頂點(diǎn),也就是說,可以由頂點(diǎn)2直接到頂點(diǎn)0,即它們有邊連接。
最終,最短路徑為1->3->2->0,距離為 A[1][0] = 6 。
顯然,這是一個逐層遞進(jìn),遞歸的過程。
算法實(shí)現(xiàn)
基本定義
// 表示無窮大 即不可達(dá)public static int MAX = Integer.MAX_VALUE;// 距離矩陣public int[][] dist;// 路徑Path矩陣public int[][] path;核心算法
// 核心算法for(int k = 0 ; k < size ; k++){for(int i = 0;i < size;i++){for(int j = 0 ;j < size;j++){ // 判斷如果 ik距離可達(dá)且 kj距離可達(dá) 且 i和j的距離是否大于 i-> k 與 k->j的距離和if( dist[i][k] != MAX && dist[k][j] != MAX && dist[i][j] > (dist[i][k] + dist[k][j]) ){path[i][j]= k;dist[i][j]= dist[i][k] + dist[k][j];}}}}運(yùn)行結(jié)果
源碼下載
Floyd算法java實(shí)現(xiàn)-源碼下載
Floyd算法java實(shí)現(xiàn)
看完這篇文章如果你還不會Floyd,請留言評論。
轉(zhuǎn)載于:https://www.cnblogs.com/Halburt/p/10756572.html
總結(jié)
以上是生活随笔為你收集整理的【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机存储
- 下一篇: P2921 [USACO08DEC]在农