演算法導論第22章:基本的圖演算法
目錄
圖的表示
1.鄰接矩陣(Adjacency Matrix)
2.鄰接連結串列(Adjacency List)
3.完善鄰接連結串列(Implementing Adjacency List)
4.握手定理:無向圖所有結點的度之和 = 邊數 * 2
特殊的圖
1.樹(Tree)
2.有向無環圖(Directed Acyclic Graph)
3.二分圖(Bipartite Graph)
圖的遍歷
1.深度優先搜尋
2.廣度優先搜尋
拓撲排序(Topological Sort)
輸入:DAG圖
輸出:如果e(u, v),則u在v的前面(結果不唯一)
思路一: O(n² + m)
①找到一個入度為0的點,加入到答案,把它的前向邊全部刪除;
②重複這一過程。
思路二:Θ(n + m)
①預計算所有點的入度
②把入度為0的點加入佇列
③對於每個在佇列中的點的連結串列,減去對應點的入度,若入度為0,加入佇列
④重複,直到佇列空
加入佇列的順序即為拓撲序
思路三:Θ(n + m)
深度優先搜尋,記錄u.f為u結點鄰接連結串列被掃描完之後的時間,按f從大到小排序即為拓撲序
只需證明:若e(u, v)則u在v前面。
e被探索時,v不可能為灰色,因為這意味這環;
若v為白色,v必為u的後代,u肯定後被處理完;
若v為黑色,v.f已經確定,必定小於u.f
強連通分量(Strongly Connected Components)
Kosaraju’s Algorithm:Θ(V+E)
①DFS計算出所有結點的掃描連結串列完成時間f
②按f的逆序搜尋樹,合併組成森林即為SCC
歐拉回路(Eulerian Circuit)
無向圖有歐拉回路:連通,且每個節點的度為偶數
無向圖有尤拉路:連通,且擁有奇數度數的結點個數為0或2
哈密爾頓: Looks similar but very hard (still unsolved)!
題選
1.求s->t的簡單路徑條數:拓撲排序+DP
2.判斷圖是否存在環:DFS過程觀察是否有後向邊,至多V次左右
3.給定有向圖G = (V, E),如果對於所有結點對u, v ∈ V,我們有u→v或v→u,則G是半連通的。請給出一個有效的演算法來判斷圖G是否半連通的。證明演算法的正確性並分析其執行時間。
ANSWER:先執行強連通分量演算法,按照第二次DFS結點搜尋順序給連通分量按升序標號(1~k),並生成分量圖SCC(G)。在分量圖SCC(G)中,由於標號為 i+1 的連通分量不可能指向標號為 i 的連通分量,所以只需要從1~k按順序檢測是否存在(1, 2)、(2, 3) ... (k-1, k)的分量的邊。若存在,則半連通;反之,則不是半連通。演算法時間複雜度為O(V+E)。