--- tags: 演算法 --- # 演算法 期末考 筆記 ![](https://i.imgur.com/fnwPBPh.png =500x) ### 課本習題的解答多看有益身心健康 https://walkccc.me/CLRS/Chap24/24.3/ https://sites.math.rutgers.edu/~ajl213/CLRS/CLRS.html # ch12 Binary Search Trees - INORDER_TREE_WALK(x) - Θ(n) - 補充:Inorder、Preorder、Postorder tree walk ![](https://i.imgur.com/MR8wiWv.png) - TREE_SEARCH(x, k) - O(h) - ITERATIVE_SEARCH(x, k) - 例題12.2-1 哪個組合不可能是BST search 363的過程? ![](https://i.imgur.com/5TLsZPJ.png) - 參考答案:c、e是錯的 ![](https://i.imgur.com/HtjqxyG.jpg) - 例題12.2-4 Professor Bunyan發現一個屬性 search path左邊的所有節點a < search path上的所有的節點b < search path右邊的所有節點c 解釋是否正確? ![](https://i.imgur.com/0OO71on.png) - 參考答案:不正確 (以下範例假設要search key 4) ![](https://i.imgur.com/FKCsiaw.jpg) - TREE_MINIMUM(x) - O(h) - TREE_MAXIMUM(x) - O(h) - TREE_SUCCESSOR(x) 1. 如果x.right不是null,先找x右子樹的最小值TREE-MINIMUM(x.right) (ex.15的successor為17) ![](https://i.imgur.com/blh1iVN.png) 3. 如果x.right是null,往上找x的祖先y,直到找到第一個y的左子樹是x的祖先 (ex.13的successor為15) ![](https://i.imgur.com/nFN5qhJ.png) - The dynamic-set operations:O(h)(tree of height h) - 例題12.2-5 證明一個node有兩個小孩,則他的successor沒有左邊小孩,他的predecessor沒有右邊小孩 ![](https://i.imgur.com/8PRtX0S.png) - 參考解答: 假設node x有兩個小孩 x的successor是x的right tree中最小的,不可能還有左邊小孩 x的predecessor是x的left tree中最大的,不可能還有右邊小孩 - Tree-Insert(T, z) - O(h) - Tree-Delete(T, z) - O(h) - Transplant(T, u, v) - Replace the subtree of u with the subtree of v - TREE_MINIMUM(x) Deletion 1. z has no children 2. z has just one child a. 若z.left = NIL,z.right取代z b. 若z.right = NIL,z.left取代z 4. z has two children **取y為Tree-Minimum(z.right)** c. 若y.p=z,y取代z,z的左子樹變成y的左子樹 d. 若y.p!=z,先將y的右子樹取代y,再將y取代z,z的左子樹變成y的左子樹 (這裡要注意y是z的右子樹的最小值,不會有left,所以圖上y.left都畫NIL) ![](https://i.imgur.com/1gs8yPz.png) The dynamic-set operations:O(h) # ch13 Red-Black Trees - 13.1 Properties of red-black tree - 在最壞的情況下花費O(log n)時間 - 紅黑樹是一種BST額外增加一個bit紀錄顏色(紅/黑) - 透過顏色標記的限制方式,讓the root to a leaf的path不會超過其他path的兩倍,使BST大約平衡 - 符Red-Black Tree的條件(可能會考如何判斷是不是紅黑樹 ex.課本例題13.1-2) 1.每個點不是紅就是黑 2.root是黑色 3.所有leaf(NIL)是黑色 4.如果某個節點是紅色,那他的小孩一定是黑色 5.以某個節點為起點,往下到所有葉子的的路徑上的黑點數量相同 ![](https://i.imgur.com/ikjEB3C.png) - Lemma13.1:A red-black tree with n internal nodes has height at most **2lg(n+1)**. - 13.2 Rotations - The code for RIGHT-ROTATE is symmetric. - Both LEFT-ROTATE and RIGHT-ROTATE run in O(1) time. ![](https://i.imgur.com/XWwny7x.png) - 可能會考如何畫rotation前後如何畫圖(ex.如下圖) ![](https://i.imgur.com/Um8UQFP.png) - 13.3 Insertion - O(lg n) - Insert Node的方法和Binary Search Tree大致相同相同,假設insert Node z,最後要分別做以下動作讓樹的結構還是一個RB-Tree - z.left=NIL - z.right=NIL - z.color=Red - RB-INSERT-FIXUP(T, z) - RB-INSERT-FIXUP(T, z) ![](https://i.imgur.com/E8B9nx3.png) - Insert後如果z的parent是Red時 1. 如果z的parent是z的爺爺的左邊小孩(z.p=z.p.p.left),有三種情況與處理方式 **Case 1: z’s uncle y is red** ToDo:將z的parent和z的uncle顏色換成black,把z的爺爺換成red,z變成的爺爺(z=z.p.p),如圖a到圖b的過程 **Case 2: z’s uncle y is black and z is a right child** ToDo:z變成z的parent(z=z.p),進行LEFT-ROTATE(T, z),如圖b到圖c的過程 **Case 3: z’s uncle y is black and z is a left child** ToDo:將z的parent變成黑色,將z的爺爺變成紅色,再進行RIGHT-ROTATE(T, z.p.p),如圖c到圖d的過程 **重要:最後要把root圖黑(無論如何root一定要是黑色!!!)** 2. 如果z的parent是z的爺爺的右邊小孩(z.p=z.p.p.right)的三種情況與處理方式,只要把上面情況的left/right互換即可 - 要隨時注意z和y的位置變化比較好理解 ![](https://i.imgur.com/7ZOkrbx.png) - 例題13.3-2 Show the red-black trees that result after successively inserting the keys 41; 38; 31; 12; 19; 8 into an initially empty red-black tree. - 參考答案: ![](https://i.imgur.com/GPlRkYx.png) - 13.4 Deletion - O(lg n) - RB-DELETE(T,z) - 如果被刪除的節點是紅色 => RB tree的平衡還在 - **如果被刪除的節點是黑色 =>會違反RB Tree的原則,要執行RB-DELETE-FIXUP** - RB-DELETE-FIXUP(T, x) ![](https://i.imgur.com/Ihcc5Cg.png) -如果x不是root && x是黑色 - 觀念:不管x點是紅還是黑,y少掉的黑帶在x身上 => 只要是x都多帶一個黑 1. 如果x是x的parent的左邊小孩(x=x.p.left),有四種情況與處理方式 **Case 1: x’s sibling w is red** ToDo:w塗黑,x的parent塗紅,LEFT-ROTATE(T, x.p),new w為x.p.right,如圖a **Case 2: x’s sibling w is black, and both of w’s children are black** ToDo:w塗紅,new x為x.p,如圖b **Case 3: x’s sibling w is black, w’s left child is red, and w’s right child is black** ToDo:w塗紅,w.left塗黑,RIGHT-ROTATE(T,w),new w為x.p.right,如圖c **Case 4: x’s sibling w is black, and w’s right child is red** ToDo:w塗x的parent的顏色,x的parent塗黑,LEFT-ROTATE.T(x,p),new x為T.root,如圖d **重要:最後要把x(root)塗黑(無論如何root一定要是黑色!!!)** 2. 如果x是x的parent的右邊小孩(x=x.p.right),有四種情況與處理方式,只要把上面情況的left/right互換即可 - 要隨時注意x和w的位置變化比較好理解 ![](https://i.imgur.com/GaBu1uw.png) ![](https://i.imgur.com/yRP7wcX.png) - 例題13.4-3 依照13.3-2的結果依序刪除8; 12; 19; 31; 38; 41. - 參考答案: ![](https://i.imgur.com/zy2FVqg.png) # ch18 B-Trees ![](https://i.imgur.com/qtrPvV3.png) - B-Tree特性 - 每一棵B-Tree都需要在建立前指定好minimum degree ≧ t 。 - 樹上的每個節點內存放最少t-1個keys,最多2t-1個Keys。 - Root Node較為特殊,允許存放最少1個Key,最多2t-1個Keys。**如果Node已經有2t-1個keys稱為full。** - 若節點有n個keys,則有n+1個小孩 - 每個節點上的Keys都是以升序排列,相隔的兩Key,K1、K2,之間的任一子節點上的任一Key,其值必落在 K1~K2 之間。 - 所有葉節點(Leaf Node)的深度(Depth)必定相同(= tree's height h)。 ![](https://i.imgur.com/wPpSFbE.png) - Search - Run Time ![](https://i.imgur.com/p2ngJVi.png) - B-Tree 的 Search 從 Root Node 開始,比對目標 Key 與所在節點上的 Key 的值。若目標 Key 的值: 1. 小於最小Key,就往節點上最左方的子節點往下移動。 2. 落在某二鄰近 Key 之間,就往此二鄰近 Key 之間的子節點往下移動。 3. 大於最大Key,就往節點上最右方的子節點往下移動。 - 重複直到找到相符或找到葉節點還找不到為止。 - Creating an empty B-tree - O(1) - Insert (從上往下跑,遇到滿的就炸開)(滿:2t-1) - Run Time ![](https://i.imgur.com/p2ngJVi.png) - 從root沿路scan,**只要遇到full就先split** - t=3為例,Insert B、Q、L、F ![](https://i.imgur.com/Vsjma4b.png) - Delete (從上往下跑,遇到不足的就合起來)(不足:t-1) - Run Time ![](https://i.imgur.com/p2ngJVi.png) - 從root沿路掃到下面delete key的處理方式: - Case1:如果key所在的節點是葉子,直接delete,如圖b - Case2:如果key所在的節點為 Internal Node a.如果key左邊指標指到的小孩數量為t,將小孩最大值(Predecessor)取代key的位置,如圖c b.如果key右邊指標指到的小孩數量為t,將小孩最小值(Successor)取代key的位置 c.如果兩邊指標指到的小孩數量都不足t,將key和兩個小孩合併後delete key,如圖d - Case3:key經過的Node稱為x.c,如果x.c只有t-1個Key,要先將x.c補滿到t個key a.如果x.c左邊兄弟有t個key,將x.c parent key給x.c,將左邊兄弟最右邊key給x.c parent,左邊兄弟的右邊小孩給x.c。如果x.c右邊兄弟有t個key,將x.c parent key給x.c,將右邊兄弟最左邊key給x.c parent,右邊兄弟的左邊小孩給x.c。如圖f b.如果兩邊兄弟都只有t-1個key,將x.c與左邊兄弟(或右邊兄弟)與他們中間的parent key做合併,處理好後在往下走進行delete key,如圖e - t=3為例,Delete F、M、G、D、B ![](https://i.imgur.com/WVAC9Lw.png) ![](https://i.imgur.com/jUs1gx5.png) # ch19 Fibonacci Heaps - Structure of Fibonacci heaps ![](https://i.imgur.com/7z03l4B.png) - 上層為root list,root list最小的點為H.min - 曾經失去一個小孩就會變成黑色(H.mark=true) - 變成別人小孩就會變成白色(H.mark=false) - Potential function - ![](https://i.imgur.com/e4iieNq.png) = number of trees + 2 * number of marks - Maximum degree - D(n) = O(lg n) → 任何人的小孩個數頂多lgn個 - Creating a new Fibonacci heap - O(1) - Make-Fib-Heap() - Inserting a node - O(1) - Fib-Heap-Insert(H, x) - 將key insert到root list,通常放在H.min的左邊,如果新增的key比較小就指定為H.min,以下為insert key 21的範例 ![](https://i.imgur.com/04ncyZq.png) - Finding the minimum node (找最小值) - O(1) - Minimum(H) - 最小值在H.min - Uniting two Fibonacci heaps (將H1、H2合併) - O(1) - Fib-Heap-Union(H1, H2) - 將H1、H2的root list連在一起,再比較H1.min和H2.min誰比較小,指定為新的Heap的H.min - Extracting the minimum node(取出最小值) - O(D(n)) = O(lg n) - Fib-Heap-Extract-Min(H) - z=H.min,將z的兒子都放到root list,取出z,並指定z的右邊root為新的H.min,如圖b - 從H.min往右使用一個陣列紀錄degree,若遇到將相同degree的root就做合併,小的當root,一直到沒有相同degree的root,如圖c到l - 將root list最小值指定為H.min,如圖m ![](https://i.imgur.com/tqXoS3C.png) ![](https://i.imgur.com/lbKxe6q.png) - Decreasing a key (把某個key的值變小) - O(1) - Fib-Heap-Decrease-Key(H, x, k) - 用途:將key變小,就可以用Extracting the minimum node方法將key刪除 - 步驟: ***每人最多失去一個孩子,若超過,移到root list** 1. 將key值變小後放到root,如果key原本的parent為白色(H.mark=false),則塗成黑色,如圖b、c 2. 如果放到root的key原本的parent是黑色(H.mark=true),也要放到root,如圖d 3. 重新指定H.min - 以下舉例46→15和35→5 ![](https://i.imgur.com/QMTVx9y.png) - Deleting a node - O(D(n)) = O(lg n) - FIB-HEAP-DELETE(H, x) - 將要刪除的key值變成負無限大 → FIB-HEAP-DECREASE-KEY(H,x,-∞) - 取出最小值後刪除 → FIB-HEAP-EXTRACT-MIN(H) # ch21 Data Structures for Disjoint Sets - Disjoint Sets:「互斥集」的意思是一堆集合們,大家擁有的元素都不相同,也就是說**這些集合們之間都沒有交集**。 - ex. A = {1,2,3} B={4,5,6} C={1,2,7},則AB構成Disjoint Sets,AC不構成Disjoint Sets。 - Disjoint Set的操作: - MAKE-SET(x):MAKE 建立一個只含x的set。因為互斥,所以x不能在其他集合出現過。 - UNION(x,y):Union 是將兩個含有x和y的集合合併。 - FIND-SET(x):Find 則是查詢某個元素所在的集合。 - 參數定義: - m:總共有m個opterations(make、union、find) - n:其中包含n個make operations - CONNECTED-COMPONENTS:一開始將每個點單獨看成不同的集合,對於每一條edge(u,v),假設u,v在不同的集合之內,就將包含他們的集合聯集起來,最後看剩下幾個集合,就是有幾個connected component。 - 例題21.1-1 ![](https://i.imgur.com/dKXmXLF.png) - 參考答案: ![](https://i.imgur.com/bvaj7u9.png) - Linked List v.s. rooted tree | | linked List | rooted tree | | -------- | ----------- | ----------- | | make | O(1) | O(1) | | union | O(n^2) 費時 | O(α(n)) 快 | | find | O(1) 快 |O(mα(n)) 慢→快| - α(n)是Ackermann’s function的反函數,其成長速率非常慢。在所有可能的應用中,α(n) <= 4 (近乎常數頂多是4) - rooted tree的find function本來很慢改善後可以變快→O(mα(n)) worst case - Linked-list representation of disjoint sets - A simple implementation of union(不考慮每個set的長度) - 以序列中第一個元素當作代表人(representative)。 ![](https://i.imgur.com/3CrkTqn.png) ![](https://i.imgur.com/t9Mtd0u.png) - A weighted-union heuristic(考慮每個set的長度,短的併到長的) - 每一個representative存放其代表的序列的長度。 - 把較短的序列附加在較長的序列之後。(可以節省union時間) - Disjoint-set forests (rooted tree) - Tree的root為代表人(representative)。 ![](https://i.imgur.com/o3qCFFm.png) - 改善running time的方法: - **Union by rank**: 由較小高度的的tree的root連到較大的tree的root。 - **Path compression**: 在執行Find-Set(x)過程中,把所有經過的node都掛在root底下。 (壓縮) ![](https://i.imgur.com/nIQYIyx.png) # ch22 Elementary Graph Algorithms (初級圖演算法) ## 22.1 Representations of graphs(圖形表示) 1. 無方向(Undirected graph: no orientation is specified) 2. 有方向(Directed graphs: Oriented, the adjency matrix is not necessarily symmetric) 3. 矩陣 [adjacency-matrix representation (dense)] 4. 串列 [adjacency-list representation (sparse)] - 無方向:矩陣&串列表示法 ![](https://i.imgur.com/oksqBU5.png =400x) - 有方向:矩陣&串列表示法 ![](https://i.imgur.com/uZYtMho.png =300x) ## 22.2 Breadth-first Search (BFS:廣度優先) - BFS(G,s):圖形G中,計算*s*到其他點的最短距離 - Analysis Complexity:O(V+E) - 應用:**Queue(先進先出)**;ENQUEUE(Q,s):s放入Queue中;DNQUEUE(Q):Queue中取值 - 屬性 - color:顏色註記[白色(未搜尋過),灰色(已搜尋過,丟Queue中)和黑色(搜尋完成,沒有相鄰點,移出Queue)] - d:距離(distance ) - π:前一個節點 - adj[u]:*u*點相鄰的點集合 ![](https://i.imgur.com/XZifbQO.png =300x) - line:1-8,初始化 - line:1-4,*s*外的點給予初值 - line:5-7,*s*點給予初值 - line:8,Queue給予初值 - line:9,起點s放入Queue中,透過Queue的特性完成廣度優先搜尋 - line:10,持續執行到Queue為空為止 (loop level1) - line:11,取出Queue的值為*u* - line:12,將*u*相鄰的點依序取出為*v* (loop level2) - line:13-17,若*v*顏色為白色者(未搜尋過)則註記為灰色,將該點*v*的距離(*d*)紀錄為*u*的距離加1,並留下v的前一個節點(*π*)為*u*後放入放入Queue中 - line:18,將u標記為黑色視為以搜尋完成所有相鄰的點 ![](https://i.imgur.com/4lIREN9.png) > 參考網址:Graph: Breadth-First Search(BFS,廣度優先搜尋) > http://alrightchiu.github.io/SecondRound/graph-breadth-first-searchbfsguang-du-you-xian-sou-xun.html - Shortest paths:當我們用BFS找端點對端點最短路時,從出發點開始,第一次遍歷到終點時過的那條路徑就是最短的路徑。 ## 22.3 Depth-First Search (DFS:深度優先) - Complexity:O(V+E) - 應用:**Recursion**的方式做深度優先持續往下鑽 - 屬性 - color:顏色註記[白色(未拜訪過),灰色(已拜訪過,可拜訪相鄰的點)和黑色(拜訪完成,沒有相鄰點可拜訪)] - d:發現(discovered) - f:完成(finished) - π:前一個節點 - adj[u]:*u*點相鄰的點集合 ![](https://i.imgur.com/5BWUNdu.png) - line:1-3,loop所有點初始化 - line:4,time初值 - line:5-7,loop所有點*u*,判斷白色(未拜訪過)的點後執行[DFS-VIST(G,u) Recursion]recurse ![](https://i.imgur.com/vig8dZc.png) - line:1-3,透過time累計拜訪次數,並將目前次數賦予目前拜訪的點 *u.d* 後將該點顏色註記為灰色 - line:4-7,loop所有*u*相鄰的點*v*,判斷白色(未拜訪過)的點,紀錄前一個節點(*π*)為*u*後執行[DFS-VIST(G,v) Recursion]recurse - Classification of edges: 1. Tree edges:2-4以外的邊。 2. Back edges(B):經過的邊拜訪到的點為灰色時。 3. Forward edges(F):經過的邊拜訪到的點為黑色時。 4. Corss edges(C):不同component的edge。 - ![](https://i.imgur.com/BGOQKsY.png) > 參考網址:Graph: Depth-First Search(DFS,深度優先搜尋) > http://alrightchiu.github.io/SecondRound/graph-depth-first-searchdfsshen-du-you-xian-sou-xun.html ## 22.4 Topological Sort (拓撲排序) - 有方向無循環(directed acyclic graph) - 正確的Topological Sort可能不止一種 ![](https://i.imgur.com/iz9agg9.png) - 透過DFS(G)計算各節點完成時間(標記黑色的順序) - 將各節點完成時間由大到小排序 ![](https://i.imgur.com/6wrfE37.png) - 做DFS下鑽到最後一個點時,因沒有相鄰的而返回表示無循環;反之,有相鄰的點但皆為灰色點而返回表示有循環 > 參考網址:Graph: 利用DFS尋找DAG的Topological Sort(拓撲排序) > http://alrightchiu.github.io/SecondRound/graph-li-yong-dfsxun-zhao-dagde-topological-sorttuo-pu-pai-xu.html ## 22.5 Strongly connected components (強關聯元件) - 有向圖 - Complexity:O(V+E) ![](https://i.imgur.com/oGtrGPQ.png) - 透過DFS(G)計算各節點完成時間(*u.f*:標記黑色)[如下圖(a)] - 將圖的所有方向顛倒產生G^T^(Transpose of Graph)[如下圖(b)] - 透過DFS(G^T^)計算,DFS主程式的loop按line:1的完成時間(*u.f*)遞減順序執行 - line:3運行DFS主程式的loop每判斷為白色(未拜訪過)做recurse為一個component(each tree in the depth-first forest) ![](https://i.imgur.com/tXoMDwg.png) - component graph一定是directed acyclic graph(DAG)。 > 參考網址:Graph: 利用DFS尋找Strongly Connected Component(SCC) > http://alrightchiu.github.io/SecondRound/graph-li-yong-dfsxun-zhao-strongly-connected-componentscc.html # ch23 Minimum Spanning Trees (MST,最小生成樹) - 從圖中找出最小生成樹(MST)的問題 - 無向圖(undirected graph),端點都有連接(connected)且有權重(weight)的圖,希望找出沒有循環並能連接所有點的子集合,且總權重要是最小的。 - Spanning Tree:沒有循環且連結所有點 ![](https://i.imgur.com/5zetc1H.png) ## 23.1 Growing a minimum spanning tree ![](https://i.imgur.com/stXWyS7.png) - line:1,A為邊的空集合,初始化 - line:2-4,A集合還未形成spanning tree下,持續loop找出一個對A集合是**安全**(**safe**)的邊(edge)後,聯集(union)到A集合中。 - **安全**(**safe**)定義:區分點(vertex)的集合和邊(edge)的集合,演算法中為邊(edge)的集合,而以下定義有部分在說點的集合。 - 名詞解釋: - cut(切割):點(vertex)集合,分成兩部分的partition(分割),spanning tree用的點集合 - crosses(交叉):邊(edge)集合,一個邊(edge)串連cut的partition與圖其他點的邊,稱為crossing edge - respects(尊敬):Set A中沒有任何一條edge是crossing edge - light edge(輕量邊):crossing edge中權重(weight)最小的邊 - 定理1:符合四點表示**安全**(**safe**) 1. 圖要相連、有權重且無方向的圖 2. 集合A是MST的子集合 3. 集合A要有respects 4. line:3找的邊要為crossing edge且要是light edge - 推論2:如下集合A的connected component也符合**安全**(**safe**) 1. 同定理1,2點的情境 2. 集合A中的數個connected component皆可視為一棵樹 3. 連結各個connected component的light edge(同定理4) > 參考網址:Minimum Spanning Tree:Intro(簡介) > http://alrightchiu.github.io/SecondRound/minimum-spanning-treeintrojian-jie.html - Kruskal and Prim summary - Kruskal’s algorithm:所有邊找權重由小到大完成MST - Prim’s algorithm:從一個起始點開始往外找每個點相鄰的最小權重的邊 ## 23.2 Algorithms of Kruskal and Prim ### Kruskal’s algorithm ![](https://i.imgur.com/srzVg4F.png) - line:1-3,初始化 - line:4,把圖的所有邊(edges)以權重(weight)由小到大做排序 - line:5-8,loop所有邊(edges)依權重由小到大運行,判斷邊 *u* 和 *v* 在不同集合中,便將邊(u,v)放入A集合中,*u* 和 *v* 的點集合聯集 ![](https://i.imgur.com/X8bY3rC.png) ![](https://i.imgur.com/jhTakAc.png) > 參考網址:Minimum Spanning Tree:Kruskal's Algorithm > http://alrightchiu.github.io/SecondRound/minimum-spanning-treekruskals-algorithm.html ### Prim’s algorithm ![](https://i.imgur.com/gldagMY.png) - line:1-4,初始化 - line:5,所有點丟入a min-priority queue Q based on a key attribute - line:6-7,Queue中取出最小的做為 *u* 至Queue取空為止 (loop level 1) - line:8-11,所有 *u* 的相鄰的點依序取出為 *v* (loop level 2),判斷 *v* 點仍存在於Queue中,且 *u* 到 *v* 之間的權重找最小者 ![](https://i.imgur.com/TAbgIxD.png) > 參考網址:Minimum Spanning Tree:Prim's Algorithm > http://alrightchiu.github.io/SecondRound/minimum-spanning-treeprims-algorithm.html # ch24 Single-Source Shortest Paths - shortest-path weight δ(u,v) from u to v ![](https://i.imgur.com/l8wXmer.png) - v.d = d[v]指的是目前到v點的距離 v.π指的是v的前一個點(predecessor) - single-source shortest-paths problem與他的三種變形 (Variants) 1. single-source shortest-paths problem 從單一vertex,抵達Graph中其餘所有vertex之最短路徑。(一對多) 2. Single-destination shortest paths problem 從Graph中的每一個vertex抵達某個特定vertex之最短路徑,剛好與第1種問題的子問題相反。(多對一) 3. Single pair shortest path problem 從單一vertex,抵達某個特定vertex之最短路徑,此為第1種問題的子問題。(一對一) 4. All-pair shortest paths problem Graph中的所有vertex抵達其餘所有vertex之最短路徑。(多對多) - 若把每一個vertex都當作起點,即可利用第1種問題之方法解決。 - 不過Ch25介紹的**Floyd-Warshall Algorithm**有更好的答案。 - Optimal substructure of a shortest path - Optimal substructure定義:原問題的最佳解是由其子問題得的最佳解算出來的 - Lemma 24.1. Subpaths of shortest paths are shortest paths(最短路徑中的子路徑也都是最短路徑) ![](https://i.imgur.com/5wxJ6H0.png) - 順帶一提:最長路徑不為Optimal substructure - Negative-weight edge/cycle - 最短路徑的weight可正可負,但不能包含負的cycles(Negative cycles),因為一直繞會變-∞ ex.下圖的ef和hij,都造成Negative cycles使結果變成-∞ ![](https://i.imgur.com/vebLlEf.png) - Shortest paths are not necessarily unique, and neither are shortest-paths trees Shortest paths可以有多組解,如下圖b和c陰影路徑都呈現了最短路徑的解,都以s為起點但結構不同的shortest-paths trees ![](https://i.imgur.com/BwbUFq0.png) - Relaxation 鬆弛 考慮是否使用u→v這條線edge(u,v)會比較好? 如果v.d > u.d + w(u,v),則可以走edge(u,v) 此時紀錄v.d的值為u.d + w(u,v),v.π = u time complexity= O(1) ![](https://i.imgur.com/7mnqGmD.png)![](https://i.imgur.com/EyXl1BR.png) - Properties of relaxation (不想看就跳過) ![](https://i.imgur.com/K1m2CNN.png) - The Bellman-Ford algorithm 貝爾曼-福特演算法 - Time complexity O(VE) - 權重可以是負的,但不能有負的cycle ![](https://i.imgur.com/EDhFHSr.png) - 參考課本圖解 - 依序對所有edge進行Relax(),只要distance有縮短就替換掉路徑 ![](https://i.imgur.com/b0xlnBI.png) - 或者參考網址:http://alrightchiu.github.io/SecondRound/single-source-shortest-pathbellman-ford-algorithm.html hint: predecessor代表個點的前一個點, distance代表目前為止這個點計算出來的最短路徑距離 一開始所有點的predecessor都設定為-1,所有點的distance都設定為∞ 接著依序對所有edge進行Relax(),只要distance有縮短就替換掉路徑 ![](https://i.imgur.com/nCRm6IV.png) - Single-source shortest paths in directed acyclic graphs(有向無環圖) - Time complexity O(V+E) - 先把topological sort做完,再沿路relax ![](https://i.imgur.com/sksvtbH.png) ![](https://i.imgur.com/PT8uoUF.png) - 補充: 之前說過shortest path是簡單的題目,longest path是難的題目,但是如果是directed acyclic graphs(有向無環圖),則longest是簡單的題目。 - Dijkstra’s algorithm 戴克斯特拉演算法 - Time complexity O(V^2) (使用BFS方法) ![](https://i.imgur.com/ZFRWNBL.png) - 權重不能有負號 - 模擬BFS方法沿路relax,但途如果有多個點可以走,EXTRACT_MIN(Q)取值最小的點繼續往下走,如圖b(5比10小),如圖c(7比8和14小),以此類推,直到所有點都已經塗黑 - EXTRACT_MIN(Q)即是採用Greedy strategy ![](https://i.imgur.com/MHny7mm.png) ![](https://i.imgur.com/FPTNgl5.png) # ch25 All-Pairs Shortest Paths ## 25.1 Shortest paths and matrix multiplication - dynamic-programming algorithm - Initial ![](https://i.imgur.com/OTXu3sV.png) - Then ![](https://i.imgur.com/LVBrzvo.png) - Time Complexity O(n^4) - 改善running time => using repeated squaring (例如W^4 寫成 W^2 * W^2,減少計算次數) => Time Complexity ![](https://i.imgur.com/2ZunHdT.png) ![](https://i.imgur.com/vYZS639.png) ## 25.2 The Floyd-Warshall algorithm - Time complexity O(N^3) - 從vertex(i)走到vertex(j),逐一引入中繼點vertex(k) ![](https://i.imgur.com/yaJoWqJ.png) ![](https://i.imgur.com/jAlhI7c.png) 為「已將集合K{1,2,3,...k}中的所有vertex作為中繼點引入集合S」後,從起點vertex(i)走到終點vertex(j)的路徑之成本。 ![](https://i.imgur.com/cPkTmrw.png) ![](https://i.imgur.com/NMwhU0G.png) - 參考課本圖解:計算每一個點i到其他點j的距離(ex. 看i=1那行,1到2的距離為3,1到3的距離為8,1到4的距離為∞...) ![](https://i.imgur.com/gTa4bze.png) - 或者參考網址內的圖解:http://alrightchiu.github.io/SecondRound/all-pairs-shortest-pathfloyd-warshall-algorithm.html#floyd - Initial ![](https://i.imgur.com/SqM6wXE.png) - 原本C→B,d=∞。引入A當中繼點,變成C→A→B,d=6 ![](https://i.imgur.com/U5j4MAL.png) - 原本A→C,d=6。引入B當中繼點,變成A→B→C,d=0 - 原本A→D,d=9。引入B當中繼點,變成A→B→D,d=5 ![](https://i.imgur.com/iO5qAM6.png) - 依此類推... ### Transitive closure of a directed graph (傳遞閉包) ![](https://i.imgur.com/X66pTL5.png) ![](https://i.imgur.com/cBugzFm.png) # ch26 Maximum Flow ## 26.1 Flow networks Flow networks and flows ## 26.2 The Ford-Fulkerson method (福特福克森方法) 計算網絡流的最大流的貪心算法。 之所以稱之為「方法」而不是「算法」,是因為它尋找增廣路徑的方式並不是完全確定的,而是有幾種不同時間複雜度的實現方式。 FORD-FULKERSON-METHOD(G,s,t) 三個重要應用: 1. Residual networks (剩餘網路) 2. Augmenting paths 3. Cuts ### Residual networks (剩餘網路) residual capacity (剩餘容量) ### Augmenting paths ### Cuts S在左;T在右,中間切一刀 > Corollary 26.5 > The value of **any flow** f in a flow network G is bounded from above by the capacity of **any cut** of G. > 流量網絡G中任何流量f的值都由G的任意割斷的能力從上方限制。 > Theorem 26.6 (Max-flow min-cut theorem) ### The basic Ford-Fulkerson algorithm FORD-FULKERSON(G,s,t) running time:O(E|f*|) ## 26.3 Maximum bipartite matching 最多的配對 ![](https://i.imgur.com/rIczMPv.png =400x) --- | ch | algorithm | Complexity | | -------- | -------- | -------- | | ch12 | Binary Search Trees | O(h) | | ch13 | Red-Black Trees | O(log n) | | ch18 | B-Trees | O(th)=O(t log~t~n) | | ch19 | Fibonacci Heaps | O(lg n) | | ch21 | Data Structures for Disjoint Sets | O(mα(n)) | | ch22 | Elementary Graph Algorithms | O(V+E) |