1. 程式人生 > >有向圖之每一對頂點之間的最短路徑

有向圖之每一對頂點之間的最短路徑

1 上一篇部落格介紹了使用迪傑斯特拉演算法求某個頂點到其他頂點的最短路徑,這一篇介紹使用弗洛伊德(Floyd)演算法求每一對頂點之間的最短路徑,當然也可以使用迪傑斯特演算法來求,求n次就行了。

2 弗洛伊德演算法仍從圖的帶權鄰接矩陣出發,其基本思想是:

2.1 假設求從頂點vi到vj的最短路徑

2.2 如果從vi到vj有弧,則從vi到vj存在一條長度為arcs[i][j]的路徑,該路徑不一定是最短的,尚需要進行n次試探。

2.3 首先考慮路徑(vi,v0,vj)是否存在(即判斷(vi,v0)和(v0,vj)是否存在),如果存在,則比較(vi,vj)和(vi,v0,vj)的路徑長度取長度較短者為從vi到vj的中間頂點的序號不大於0的最短路徑。

2.4 假設在路徑上再增加一個頂點v1,也就是說,如果(vi,....,v1)和(v1,..,vj)分別是當前找到的中間頂點的序號不大於0的路徑,那麼(vi,...,v1,...,vj)就有可能是從vi到vj的中間頂點的序號不大於1的最短路徑。

2.5 將它和已經得到的從vi到vj中間頂點序號不大於0的最短路徑相比較,從中選出中間頂點的序號不大於1的最短路徑之後,再增加一個頂點v2,繼續進行試探。

2.6 以此類推,直到全部求出來。

3 解釋

3.1 2.2步應該都明白,那麼2.3步什麼意思呢?假如vi到vj有直接路徑,vi經過v0到vj也有路徑,這條路徑之可能有這三個頂點,因為v0前面不可能再有頂點了,v0在陣列中儲存的順序最靠前,(vi,v0,vj)和(vi,vj)比較,結果肯定是中間頂點不大於0的最短路徑。

3.2 2.4步呢?類似2.3步,vi到v1有路徑,中間可能會經過v0頂點,v1到vj有路徑,中間也有可能經過v0頂點,那麼(vi,..,v1,...vj)其實可能是(vi,v0,v1,vj),也有可能是(vi,v1,vj);就是經過的若干頂點中最大的就是v1,不能有比v1大的,求出來的路徑就有可能是從vi到vj的中間頂點的序號不大於1的最短路徑。

3.3 這樣依次類推,依次插入其他頂點。

4 疑惑

例圖


 核心程式碼

for(u=0;u<g.vertnum;u++){

        for(v=0;v<g.vertnum;v++){

            for(w=0;w<g.vertnum

;w++){

                if(D[v][u]+D[u][w]<D[v][w]){//從v經u到w的一條路徑更短

                    D[v][w]=D[v][u]+D[u][w];

                    for(i=0;i<g.vertnum;i++){

                        p[v][w][i]=p[v][u][i];

                    }

                }

            }

        }

    }

為什麼根據上述的步驟就能求出每一對頂點的最短路徑呢?

假如求 a到b的最短路徑,如圖,a到b有直接路徑,但是不一定是最短的,所以要試探在中間依次插入a , b , c , d頂點比較。很明顯,依照迴圈a經過d到b的路徑最短。我們可以撥開迴圈看看,當v=0,w=1,u=2時(即a,c,b,插入a和b時可以忽略不看,對結果沒影響),看a到c,c到b的路徑,a到c有直接路徑,c到b當經過d時才有路徑,而這個時候u=2,c到d還沒有路徑,所以這個肯定比a直接到b的路徑長;當v=0,w=1,u=3時,看a到d,d到b的路徑,a到d的路徑當插入c時就已經求出來了,d到b有直接路徑,所以這個時候比較(a,d,b)和(a,b)很明顯,前者小。所以a到b的最短路徑也求出來了。是不是還有點暈?來看關鍵點,圖上每一對頂點之間的最短路徑,都是同步在求,求a到b的最短路徑,d到b的最短路徑和求a到d的最短路徑經過的中間點是一樣的(因為u是最外層迴圈),因為d是最後一個頂點(在陣列中儲存的按順序來看),所以a到d和d到b之間的最短路徑在前面都已經求出來了,所以這樣就能夠求出來每一對頂點之間的最短路徑(vi到vj的最短路徑上需要經過若干頂點,在若干頂點中,位置最大的頂點vx,那麼要等到插入這個頂點的時候才能把最短路徑求出來,因為vi到vx的最短路徑前面插入小的頂點的時候已經求出來了,vx到vj也是)。不管vi到vj的最短路徑經過那個頂點,如果這個頂點的位置小,在前面迴圈就能求出來,如果這個頂點的位置大,在後面的迴圈能求出來。如下圖,是最簡單的例圖,摸索摸索應該能明白弗洛伊德演算法的思路吧。

c語言實現程式碼: [email protected]:hglspace/GetShortestPath2.git

相關推薦

一對頂點之間路徑

1 上一篇部落格介紹了使用迪傑斯特拉演算法求某個頂點到其他頂點的最短路徑,這一篇介紹使用弗洛伊德(Floyd)演算法求每一對頂點之間的最短路徑,當然也可以使用迪傑斯特演算法來求,求n次就行了。 2 弗洛伊德演算法仍從圖的帶權鄰接矩陣出發,其基本思想是: 2.1 假設求從頂點

12.帶權中任意兩點間的路徑

其實它的程式碼理解起來真的挺難的我覺得!!! 昨天看了一下午感覺晦澀難懂,還是matlab好用,直接呼叫函式就可以了!!! 不過這裡還是得跟大家介紹一下: 1.問題的理解: 像這種帶權的有向圖,每一行都表示該行標號對應列標號的有向權值,本身到本身的數值為0,沒辦法

演算法---頂點路徑

3.2、額外空間儲存2*(n*n)def floyd_warshall(W): import copy #需要兩個n*n矩陣的額外儲存 D_in = copy.deepcopy(W) D_ret = copy.deepcopy(W) k = 0 while k

網中任意一對頂點之間路徑 Floyd演算法

       有向網中欲知任意一對頂點之間的最短路徑常用Floyd演算法,基本思想是任意一對頂點vi與vj,逐步在其中加入一箇中間節點v0,..,vk,...vn,若比原路徑短則更新最短路徑,經過n次比較和修正後,vi到vj的最短路徑可以求出。具體程式碼及相關注釋如下 //

對結點之間路徑的C++實現

轉載本部落格上原創文章者,請註明出處。 Dijkstra演算法和Bellman-Ford演算法只能計算出起始點到其他各點的最短路徑,但不能計算任意兩隊頂點之間的最短路徑。若真想利用這兩張演算法,可以來一個迴圈,每次讓不同的頂點成為起始頂點,這樣也可以解決,但這種方法效率比較

spark primer 計算每個每個頂點之間路徑

edge.txt (邊資料) 1 2 2 1 3 5 1 4 1 2 3 2 3 4 2 4 5 3 5 1 2 vertex.txt(頂點資料) 1 2 1 3 1 4 2 3 3 4 4 6 5 1 package m

從一個頂點到其餘各個頂點路徑

目錄 從一個頂點到其餘各個頂點最短路徑的簡介 舉例以及詳細分析 程式碼塊 測試結果 從一個頂點到其餘各個頂點最短路徑的簡介(又名單元最短路徑) 1.定義概覽 Dijkstra(迪傑斯特拉)演算法是典型的單源最短路徑演算法,用於計算一個節點到其他所

Floyd演算法求解一對頂點之間路徑2

 問題描述:   已知一個各邊權值均大於 0 的帶權有向圖,對每對頂點 vi≠vj,要求求出每一對頂點之間的最短路徑和最短路徑長度。 解決方案: 1.每次以一個頂點為源點,重複執行迪傑斯特拉演算法n次。這樣,便可求得每一對頂點之間的最短路徑。總的執行時間為O(n3)。

一對頂點之間路徑----Floyd演算法----(附完整程式碼)

1.Floyd演算法 2.輸出每兩對頂點之間的最短距離 #include<stdio.h> #include<stdlib.h> #define MaxVertexNum 100 #define INFINITY 65535 //#define MaxSize 1

中兩個結點之間是否存在一條路徑

public enum State{Unvisited,Visited,Visiting;}public  static boolean search(Graph g,Node start ,NLinkedList<E>{//當作佇列使用LinkedList<Node> q=new L

一對頂點之間路徑【Floyd】

演算法總結: ①Dijkstra演算法用的是貪心策略,每次都找當前最短路徑的下一個最短距離點。所以不適合帶有負權的情況。至於時間效率通過各種優化可以到達不同的程度。但是樸素的Dijkstra演算法永遠是最穩定的。 ②Bellman-Ford演算法是Dijkstra的一種變式,它摒棄了貪心的策略,但是每次都需

計算無無權中兩點間所有的路徑

  一、例子 如上圖,節點0到節點5的最短路徑長度為3,有兩條最短路徑: 路徑1:0 — 1 — 4— 5 路徑2:0 — 1 — 2— 5 二、相關名稱 tempLadder:             儲存當前正在計算的路徑 canditStack:          

兩點之間路徑:弗洛伊德算法

int code 指定 matrix ++ 計算 之間 logs 執行函數 弗洛伊德算法是計算無向有權圖中兩點間最短路徑的算法,復雜度為O(n^3)。其思路是將兩點間距離分為過(指定的)第三點或是不過,然後取它們的最小值,如此循環就可以得到兩點之間真正的最小值。 void

論動態規劃演算法——Floyd路徑

前言 推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。 Floyd演算法 Floyd是一種經典的多源最短路徑演算法,它通過動態規劃的思想來尋找給定加權圖中的多源

資料結構 論中求單源路徑實現 純程式碼

如下有向圖 求出單源起點A到所有其他節點的最短路徑 完整程式碼: #include <stdio.h> #include <memory.h> //圖論的迪傑斯特拉演算法 #define FINITY 200 #define M 20 //單源點頂點到其他

的鄰接矩陣表示與路徑演算法( Dijkstra )程式碼實現

#include <stdio.h> #define MAX_VERTEX_NUM 20 //最大頂點個數 typedef int VRTYPE, InfoType; typedef enum {DG, DN, UDG, UD

紫書第十一章-----論模型與演算法(路徑Dijkstra演算法Bellman-Ford演算法Floyd演算法)

最短路徑演算法一之Dijkstra演算法 演算法描述:在無向圖 G=(V,E) 中,假設每條邊 E[i] 的長度為 w[i],找到由頂點 V0 到其餘各點的最短路徑。 使用條件:單源最短路徑,適用於邊權非負的情況 結合上圖具體搜尋過程,我繪出下表,方便

貪心演算法用優先佇列解決路徑問題(Dijkstra演算法)

#include <iostream> #include <cstdio> #include <stack> #include <cstring> #include <queue> #include <cstdlib> using na

論演算法(一)--路徑的DFS/BFS解法(JAVA )

最短路徑–城市路徑問題: 問題描述:求從1號城市到5號城市的最短路徑長度 Input: 5 8 1 2 2 1 5 10 2 3 3 2 5 7 3 1 4 3 4 4

簡單論:遍歷所有路徑

今天遇到了兩道要求遍歷所有最短路徑的題,我一直做不對的原因竟是我把無向圖當成了有向圖,鬱悶的要死。 解決遍歷所有最短路徑,其實思路很簡單,首先通過經典演算法[各種演算法,Dijkstra,bellman,floyd]求出最短路徑的長度,然後就只能DFS來找尋起始點、終點一樣