目錄
- 1.廣度優先搜索及其擴展應用
1.1 廣度優先搜索
參見基本的圖算法
1.2 分支限界法
參見分支限界法——對解空間的一種策略搜索(廣度優先搜索)
1.3 最小生成樹的Prim算法
參見最小生成樹
1.4 單元最短路徑的SPFA算法
參見最短路徑專題
1.5 單元最短路徑的Dijstra算法(類似于Prim和分支限界法)
參見最短路徑專題 - 2.深度優先搜索及其擴展應用
2.1 深度優先搜索
參見基本的圖算法
2.2 拓撲排序
參見基本的圖算法
2.3 有向無環圖中的單源最短路徑問題——按拓撲排序進行松弛
參見最短路徑專題
2.4 最大流的前置重貼標簽算法(有向無環圖的許可網絡的拓撲排序)
參見最大流
2.5強連通分量
參見基本的圖算法
2.6 回溯法
參見回溯算法——對解空間(搜索樹)的一種策略搜索(深度優先搜索) - 3.使用深度優先搜索或廣度優先搜索的算法
3.1 最大流FORD-FULKERSON算法
參見最大流
3.2 0/1背包問題
參見0/1背包問題——動態規劃、回溯、分支限界法對比
3.3 旅行商問題
參見旅行商(TSP)問題專題——多種方法對比
1.廣度優先搜索及其擴展應用
1.1 廣度優先搜索
- 廣度優先搜索的特點:算法始終是沿著 已發現結點和未發現結點邊界 的廣度方向向外擴展。
即算法需要在發現所有距離源節點s為k(k條邊)的所有結點之后,才會發現距離源節點s為k+1的其他節點。 - 結點分為三類:
白色:開始時都涂為白色
黑色:所有與黑色結點鄰接的結點都已被發現
灰色:其鄰接結點中可能存在未被發現的白色結點。(是已知和未知兩個集合之間的邊界。) - 執行廣度優先搜索的過程中,將構造出一棵以s為根的廣度優先樹。
-
隊列Q中管理灰色結點集
- BFS的運行時間:
1)每個結點入隊和出對最多一次,總時間為O(V)
2)對每個結點進行鄰接鏈表掃描(最多一次),因此掃描鄰接鏈表的時間為O(E)
總時間為O(V + E)
1.2 分支限界法
- 在分支限界法中,每一個活結點只有一次機會成為擴展結點。活結點一旦成為擴展結點,就一次性產生其所有兒子結點(廣度優先搜索)。在這些兒子結點中,導致不可行解或導致非最優解的兒子結點被舍棄,其余兒子結點被加入活結點表中。
然后,從活結點表中取下一節點(優先隊列中最大或最小值)成為當前擴展結點,并重復上述擴展過程。這個過程一直持續到找到所需的解或活結點表為空時為止。 - (分支限界法的本質)因此,如果算法找到了一個耗費為c的解,并且有一個部分解,它的耗費至少是c,那么就不會有該部分解的擴展生成。
1.3 最小生成樹的Prim算法
- 集合A是一棵樹,每次加入到A中的安全邊永遠是連接A和A之外某個節點的邊中權重最小的邊。
- 廣度優先搜索的思想——當從Q中取出一個點u時,即要檢查u的所有相鄰的點,并更新相關的點。
- Prim算法與分支限界法類似,利用廣度優先搜索和優先隊列思想,只不過是沒有使用分支限界思想。因為可以證明貪心選擇性質,使之可以組成一個最優解。
1.4 單元最短路徑的SPFA算法
- 建立一個先進先出的隊列用來保存待優化的結點,優化時每次取出隊首結點u,并且用u點當前的最短路徑估計值對離開u點所指向的結點v進行松弛操作,如果v點的最短路徑估計值有所調整,且v點不在當前的隊列中,就將v點放入隊尾。這樣不斷從隊列中取出結點來進行松弛操作,直至隊列空為止。
1.5 單元最短路徑的Dijstra算法(類似于Prim和分支限界法)
- 要求所有邊的權重為非負值。
- 算法維持集合S,從源節點s到該集合中每個結點之間的最短路徑已經被找到。
算法重復從結點集V-S中選擇最短路徑估計最小的結點u,將u加入到集合S,然后對所有從u發出的邊進行松弛。
2.深度優先搜索及其擴展應用
2.1 深度優先搜索
- (回溯)只要可能,就在圖中盡量“深入”。
深度優先搜索總是對最近才發現的結點v的出發邊進行搜索,直到該節點的所有出發邊都被發現為止。一旦結點v的所有出發邊都被發現,搜索則回溯到v的前驅結點,來搜索該前驅結點的其他出發邊。
該過程一直持續到從源節點可以達到的所有結點都被發現為止。 -
前驅子圖:Gπ = (V, Eπ),其中:
Eπ = {(v.π, v): v∈V且v.π ≠ NIL }
深度優先搜索的前驅子圖形成一個由多棵深度優先樹構成的深度優先森林。森林Eπ中的邊稱為樹邊。
深度優先搜索的前驅子圖可能由多棵樹組成,因為搜索可能從多個源節點重復進行。 -
結點分為三類:
白色:開始時都涂為白色
黑色:其鄰接鏈表被掃描完成后變為黑色。
灰色:其鄰接結點中可能存在未被發現的白色結點。(是已知和未知兩個集合之間的邊界。)
該方法可以保證每個結點僅在一棵深度優先樹中出現,因此,所有的深度優先樹是不相交的。 - 每個結點蓋上時間戳:
1)v.d:記錄結點v第一次被發現的時間(涂上灰色的時候)
2)v.d:對v的鏈接鏈表完成搜索掃描的時間(涂上黑色的時間)
結點v在v.d之前是白色,在v.d和v.f之間為灰色,在v.f之后是黑色。
- 運行時間:
DFS-VISIT被調用的次數剛好為一次,只有當u為白色的時候,才調用。Θ(V)。
遍歷鄰接遍歷總共執行的是Θ(E)。
總共Θ(V + E)
2.2 拓撲排序
- 使用深度優先搜索對有向無環圖進行拓撲排序
- (拓撲排序)對于一個有向無環圖G = (V, E)來說,其拓撲排序是G中所有結點的一種線性次序,該次序滿足如下條件:
如果圖G包含邊(u ,v),則結點u在拓撲排序中出于結點v的前面(如果G含有回路,則不可能排出一個線性次序)。
- 拓撲排序的本質是:按照其完成時間的逆序被排成從左至右的一條水平線。所有的有向邊都是從左指向右。
拓撲排序正確的本質是:使用深度優先搜索不產生后向邊(因為是無環的)。
2.3 有向無環圖中的單源最短路徑問題——按拓撲排序進行松弛
- 根據結點的拓撲排序來對帶權重的有向無環圖G=(V, E)進行邊的松弛的操作,便可以在Θ(V + E)時間內計算出從單個源節點到所有結點之間的最短路徑。
拓撲排序:有向無環圖包含從結點u到結點v的一條路徑,則u在拓撲排序的次序中位于v的前面。
- DAG——Directed Acyclic Graph有向無環圖
2.4 最大流的前置重貼標簽算法(有向無環圖的許可網絡的拓撲排序)
-
維持一個鏈表L,該表由V-{s, t}中的所有結點構成。
關鍵性質是,鏈表L中的結點均按照許可網絡里面的拓撲排序次序存放。(許可網絡是一個有向無環圖)
2.5強連通分量
(強連通)如果一個有向圖中任意兩個頂點互相可達,則該有向圖是強連通的。有向圖的強連通分量是“相互可達”關系下頂點的等價類。
有向圖G = (V, E)的強連通分量是一個最大結點集合 C包含于V,對于該集合中的任一對結點u和v來說,路徑 u ->...-> v和v ->...-> u同時存在,也就是u和v可以互相可達。(轉置GT)尋找連通分量的算法需要用到圖G=(V, E)的轉置,將其定義為GT = (V, ET)
ET = {(u, v): (v, u) ∈ E}
ET是由圖G中的邊進行反向而獲得的。
圖G和GT的強連通分量是完全相同的(算法)在Θ(V + E)時間使用使用兩次深度優先搜索來計算有向圖G = (V, E)的強連通分量。這兩次搜索一次運行在G上,一次運行在GT上。
-
第二次實際上是以拓撲排序的次序來訪問分量圖中的結點。
-
算法的關鍵:對GT的深度優先搜索訪問任意一個強連通分量時,從該連通分量發出的所有邊只能是通向已經訪問過的強連通分量。
2.6 回溯法
參見回溯算法——對解空間(搜索樹)的一種策略搜索(深度優先搜索)
回溯法按詞典序考慮笛卡爾積X1 × X2 × ... × Xn 。
(開始)算法最初從空向量開始,然后選擇X1中最小的元素作為x1,如果(x1)是一個部分解,算法通過從X2中選擇最小的元素作為x2繼續,如果(x1, x2)是一個部分解,那么就包括X3中最小的元素,否則x2被置為X2重的下一個元素。
(一般情況)假定算法已經檢測到為(x1, x2, ..., xj),它然后考慮向量v = (x1, x2, ..., xj, xj + 1),有以下情況:
1.如果v表示問題的最后解,算法記錄下它作為一個解,在僅希望獲得一個解時終止,或者繼續去找出其他解。
2.(向前步驟)。如果v表示一個部分解,算法通過選擇集合Xj+2中的最小元素向前。
3.如果v既不是最終解,也不是部分解,則有兩種子情況
3-1.如果從集合Xj+1中還有其他的元素可選擇,算法將xj + 1置為Xj+1中的下一個元素。
3-2.(回溯步驟)。如果從集合Xj+1中沒有更多的元素可選擇,算法通過將xj置為Xj中的下一個元素回溯;如果從集合Xj中仍然沒有其他的元素可以選擇,算法通過將xj-1置為Xj-1中的下一個元素回溯,依次類推。回溯法也可以對界進行估算,也可以對每個Xi的按照大小排序,所以回溯法與分支限界法在限界上沒什么不同。
只不過是在搜索解空間樹的方式不一樣。
3.使用深度優先搜索或廣度優先搜索的算法
3.1 最大流FORD-FULKERSON算法
- (while循環次數)一個簡單的上界分析:假設所有的容量都是整數(有理數可以通過乘以系數轉換成整數)。假設f*是一個最大流,則while循環最多執行|f*|次。因為流量值每次迭代中最少增加一個單位。
(每次循環找到一條增光路徑的時間)給定網絡G的一個流f,殘存網絡Gf中的邊由網絡G'中所有滿足條件cf(u, v) > 0的邊(u, v)所構成。因此使用深度優先搜索或者廣度優先搜索,在一個殘存網絡中找到一條路徑的時間為O(V+E') = O(E)。
因此整個FORD-FULKERSON算法運行的時間為O(E|f*|)