1. 程式人生 > >簡談DFS

簡談DFS

left 返回 路徑 過程 要求 ref sub 遍歷 分享圖片

所謂DFS就是“不撞南墻不回頭”的一種搜索。其時間復雜度為O(V+E)。

技術分享圖片

能算出從起點到終點的全部路徑,在算法執行的過程中需要一個visit[vi]數組來維護每個結點的訪問情況,這樣就能避免重復訪問。但需要註意的是對於同一起點到同一終點有多條路徑的時候,每次遞歸回溯時要重置visit[vi]的狀態。並且可以使用vector來存儲每次經過的節點。兩個同類型的vector數組可以直接比較、直接賦值的,所以DFS也就可以簡單的求出最佳路徑。

DFS在遞歸過程中的還存在一個難點就是結束遞歸開始回溯的條件設置。這裏往往在到達終點的基礎還要加上題目所限定的條件。這有一個技巧就是先一個 if(begin == end && 題目限定的條件){到達終點後要處理的邏輯} if(begin == end){return;} 正所謂把邏輯處理和返回分離避免混亂(因為會存在有時需要執行邏輯有時不需執行邏輯的情況)。

像PAT“周遊世界”的題目中就存在這樣的情況:第一次找到了能到達終點的路徑此時還不需要去做任何比較就可以直接返回,但第二次、第三次、。。。都需要去執行邏輯比較判斷每條路徑經過的站數和換乘站次數。這裏站數的統計很簡單,每次遞歸執行就把站數加一。註意在dfs函數的參數中要想維護一個參數一定要加&(引用)。

接下來在說一個DFS中提升效率的方法:剪枝以PAT“球隊食物鏈”鏈為例,此題答案要求要滿足排列{ a1 a2 ...aN }在字典序上小於排列{ b1 b2 ... bN },當且僅當存在整數K(1 <= K <= N),滿足:aK < bK且對於任意小於K的正整數i,ai

=bi。所以1號節點一定是答案集中的第一個元素,並且答案集的最後一個元素必須和第一個元素在鄰接表所表示的圖上是連通的。所以我們在每次遞歸前都檢驗一下接下來還沒訪問過點是否能到達1號節點,若不能的話就不進行之後的遞歸。

最後總結一下,dfs是圖論最基本的一個遍歷策略,適用於求路徑數目,對於非層次遍歷的題目都可考慮用次方法解決。但有時候會因時間復雜度的限制不得不放棄此方法。

簡談DFS