考研相關文章參考資料為 wjungle 大神提供的筆記

Graph

  • G=<V,E>G = <V, E> 代表圖形是由兩個非空集合組成:
    • VV: 代表頂點 (Vertex)
    • EE: 代表邊 (Edge)
  • 根據邊的類型,可分為兩類:
    • Undirected Graph (無向圖)
      • 邊不具有方向性
      • (i,j)=(j,i)(i,j) = (j,i) 代表同一邊
    • Directed Graph (有向圖)
      • 邊具有方向性
      • (i,j)(j,i)(i,j) \neq (j,i)

相關術語

  • Eulerian cycle (尤拉 cycle)
    • 從某點出發,經過每個邊各一次,又回到原點
    • 充分必要條件: 每個頂點之 degree 為偶數
  • Eulerian chain
    • 從某點出發,經過每個邊各一次,不一定要回到原點
    • 充分必要條件: 有兩個頂點之 degree 為奇數,剩餘頂點之 degree 為偶數
  • Hamiltonian Path (漢米爾頓路徑)
    • 從某點出發,經過每個頂點各一次,不一定要回到原點
    • Hamiltonian cycle: 要回到原點

  • Complete Graph (完全圖)
    • 具有最多邊數的圖
    • nn 個頂點的無向圖: n(n1)2\frac{n(n-1)}{2} 條邊
    • nn 個頂點的有向圖: n(n1)n(n-1) 條邊
  • Subgraph & Component (子圖)
  • Path
  • Path length
    • 路徑上的邊數
  • Single Path
    • 除了起點與終點可能相同之外,中間經過的頂點皆不相同
    • ex:
      • 1-2-3-4 (O)
      • 1-2-3-4-1 (O)
      • 1-2-3-2-4 (X)
  • Cycle
    • 起點與終點相同的 Single Path
    • ex: 1-2-3-4-1
  • Connected (連通)
    • 無向圖而言,任意頂點對之間皆有 Path 存在
    • Tree 可視為一個 Connected 無向圖
      • Connected 無向圖不可視為一顆 Tree: 可能會有 cycle
      • 無 cycle 無向圖不可視為一顆 Tree: 可能不連通
  • Connected Component (連通子圖)
  • Strongly Connected (強連通)
    • 無向圖而言,任意頂點對 (i,j)(i,j) 滿足:
      • ii 有 Path 可到達 jj
      • jj 有 Path 可到達 ii
  • Strongly Connected Component (強連通子圖)
  • Degree (分支度)
    • 無向圖: 該頂點連結的邊數
      • E=12Degree|E| = \frac{1}{2}\sum{Degree}
    • 有向圖分為:
      • Out-Degree (出支度): 頂點射出之邊數
      • In-Degree (入支度): 射入頂點之邊數
      • E=OutDegree=InDegree|E| = \sum{OutDegree}= \sum{InDegree}

Graph 的表示方法

Adjacency Matrix (相鄰矩陣)

  • G=<V,E>, V=nG = <V,E>,~|V| = n,則準備一個 matrix A:nnA:n * n,其中 A[i,j]=A[i, j]=
    • 1, if1,~if(i,j)(i,j) 存在
    • 0, if0,~if 不存在
  • 無向圖
    • 相鄰矩陣必為對稱矩陣 (Symmetric)
      • (i,j)=(j,i)A[i,j]=A[j,i](i,j) = (j,i) \Rightarrow A[i,j] = A[j,i]
    • 判斷邊是否存在: O(1)O(1)
      • A[i,j]A[i,j]
    • 求頂點 ViV_i 之 degree: O(n)O(n)
      • 查第 ii 行/列元素和
    • 求圖之邊數: O(n2)O(n^2)
      • 12Degree=12A[i,j]\frac{1}{2}\sum{Degree} = \frac{1}{2}\sum{\sum{A[i,j]}}
  • 有向圖
    • 行為 In-Degree,列為 Out-Degree
    • 相鄰矩陣不一定對稱矩陣 (Symmetric)
    • 判斷邊是否存在: O(1)O(1)
    • 求頂點 ViV_iIn/Out-degree: O(n)O(n)
      • 查第 ii 行/列元素和
    • 求圖之邊數: O(n2)O(n^2)
      • InDegree=OutDegree=A[i,j]\sum{InDegree} = \sum{OutDegree} = \sum{\sum{A[i,j]}}

Adjacency Lists (相鄰串列)

  • G=<V,E>, V=n, E=eG = <V,E>,~|V| = n,~|E| = e,則準備 nn 條相鄰串列,以 Vertex[1...n]Vertex[1...n] of pointer 表示,其中 Vertex[i]Vertex[i] 代表 ViV_i 之相鄰串列,記錄所有與 ViV_i 相鄰之頂點編號
    • Node: Vertex No. | Next (Link)
  • 無向圖
    • 所有相鄰串列之 Node 總數 = 2E2|E|
      • 一條邊會加入兩個相鄰串列的 Node
    • 判斷邊是否存在: O(Vi 串列長度)O(E)O(V_i~串列長度) \leq O(|E|)
      • 檢查 Vertex[i]Vertex[i] 串列中是否存在 Node VjV_j
    • 求頂點 ViV_i 之 degree: O(Vi 串列長度)O(E)O(V_i~串列長度) \leq O(|E|)
      • Vertex[i]Vertex[i] 串列長度
    • 求圖之邊數: O(V+E)O(|V|+|E|)
      • 12Degree=12Vi 串列長度\frac{1}{2}\sum{Degree} = \frac{1}{2}\sum{V_i~串列長度}
  • 有向圖
    • 所有相鄰串列之 Node 總數 = E|E|
    • 判斷邊是否存在: O(Vi 串列長度)O(E)O(V_i~串列長度) \leq O(|E|)
    • 求頂點 ViV_i 之 degree:
      • Out-Degree: O(Vi 串列長度)O(E)O(V_i~串列長度) \leq O(|E|)Vertex[i]Vertex[i] 串列長度
      • In-Degree: O(V+E)O(|V|+|E|) 求所有串列中 Node ViV_i 出現次數
    • 求圖之邊數: O(V+E)O(|V|+|E|)
      • OutDegree=Vi 串列長度\sum{OutDegree} = \sum{V_i~串列長度}

比較表

  • G=<V,E>, V=n,, E=eG = <V,E>,~|V| = n,,~|E| = e
Adjacency Matrix Adjacency Lists
空間需求 O(n2)O(n^2) O(n+e)O(n+e)
邊數少 不適合 (稀疏矩陣) 適合
邊數多 適合 不適合
判斷邊是否存在 適合 O(1)O(1) 不適合 O(e)O(e)
求邊數、連通與否… 不適合 O(n2)O(n^2) 適合 O(n+e)O(n+e)

Adjacency Multilists (相鄰多元陣列)

  • G=<V,E>, V=n,, E=eG = <V,E>,~|V| = n,,~|E| = e,圖中的每條邊用一個 Node 來表示
    • Node: ViV_i | VjV_j | Link for ViV_i | Link for VjV_j
      • Link for ViV_i: 指向下一個包含 ViV_i 的 Node
      • Link for VjV_j: 指向下一個包含 VjV_j 的 Node
    • 另準備一個 Vertex[1...n]Vertex[1...n] of pointer,其中 Vertex[i]Vertex[i] 指向第一個包含 ViV_i 的 Node
  • 空間需求: O(V+E)O(|V|+|E|)

Index Array

  • 用一個 Array 紀錄所有點之相鄰節點編號,且用一個 Index 告知其起始位置
  • 空間需求: O(V+E)O(|V|+|E|)

Incident Matrix

  • G=<V,E>, V=n,, E=eG = <V,E>,~|V| = n,,~|E| = e,則準備一個 matrix A:neA:n * e
    • eke_k 邊為 (i,j)(i,j),則 A[i,ek]=A[j,ek]=1A[i, e_k] = A[j, e_k] = 1,其餘為 0

Graph Traversal

拜訪圖中每個頂點各一次

DFS

  • 以無向圖為例
1
2
3
4
5
6
7
8
9
10
for i = 1 to n{
visited[i] = false
}

DFS(v: start vertex){
visited[v] = true
for each vertex w adjacent to v{
if(!visited(w)) DFS(w)
}
}
  • DFS order 並非唯一
    • 通常會規定依 vertex No. 小者優先走訪,如此 order 唯一

邊分類

  • 當使用 DFS 進行有向圖的遍歷,可以將邊分為 4 類:
    • Tree edge: 遍歷追蹤時所經過的邊
      • 指向的 vertex 為還未遍歷過的 (white)
    • Back edge: 指向自己的祖先
      • 指向的 vertex 為已遍歷過,但尚未 DFS 完成 (gray)
    • Forward edge: 指向自己的後代
      • 指向的 vertex 為已遍歷過,且 DFS 完成 (black)
      • discovered time 比自身晚 (大)
    • Cross edge: 指向與自己無關的 vertex
      • 指向的 vertex 為已遍歷過,且 DFS 完成 (black)
      • discovered time 比自身早 (小)
  • 遍歷順序為: uvyxwzu \rightarrow v \rightarrow y \rightarrow x \rightarrow w \rightarrow z

  • 當使用 BFS 進行有向圖的遍歷,可以將邊分為 2 類:

    • Tree edge: 遍歷時所經過的邊
    • Back edge: 遍歷時沒有經過的邊
      • 如果指向的點為 parent (父親),不為 Back edge

BFS

  • 以無向圖為例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for i = 1 to n{
visited[i] = false
}

BFS(v: start vertex){
visited[v] = true
queue Q
Q.push(v)
while(!Q.empty()){
u = Q.front()
Q.pop()
for each vertex w adjacent to u{
if(!visited(w)){
visited[w] = true
Q.push(w)
}
}
}
}
  • BFS order 並非唯一
    • 通常會規定依 vertex No. 小者優先走訪,如此 order 唯一

比較表

DFS BFS
資料結構 Stack Queue
時間 (Adjacency Matrix) O(n2)O(n^2) O(n2)O(n^2)
時間 (Adjacency Lists) O(e)O(e) / O(n+e)O(n+e) O(e)O(e) / O(n+e)O(n+e)
  • 對於二元樹而言
    • DFS: 類似 Preorder Traversal
    • BFS: 類似 Level-order Traversal

Spanning Tree (展開樹/生成樹)

  • 給定一個 connected 無向圖 G=<V,E>G = <V,E>,令 S=<V,T>S = <V,T>GG 的一個 Spanning Tree,則 SS 滿足:
    • E=T+BE = T + B
      • EETree edge
      • BBBack edge
    • SS 中,任何頂點對之間,只存在一條 (unique) simple path
    • 若自 BB 中任取一邊加入 SS 中,必定會形成一個 (unique) cycle
  • GGunconnected,則沒有 Spanning Tree
  • GGconnected,則 Spanning Tree1\geq 1
  • GG 的頂點數為 $ n$,則其 Spanning Tree 的邊數必為 n1n - 1
  • 一個 connected 無向圖 GG 的任意兩個 Spanning Tree (若存在) 必有共同邊?
    • False: 不一定
    • 反例: 4 個頂點的完全圖 (Z 字形連接)

Minimum Spanning Tree (最小生成樹)

  • 給定一個 connected 無向圖 G=<V,E>G = <V,E>,其邊上附有成本 (加權) 值,則在 GG 的所有 Spanning Tree 中具有最小的邊成本總和
  • 若圖中有多條邊具有相同成本,則 Minimum Spanning Tree$ 可能 \geq 1$棵
  • 若圖中每條邊之成本皆不同 (unuque),則 Minimum Spanning Tree 唯一
  • Spanning Tree 之演算法 (Greedy strategy):
    • Kruskal’s Algorithm
    • Prim’s Algorithm
    • Sollin’s Algorithm

Kruskal’s Algorithm

  • 給定一個 connected 無向圖 G=<V,E>G = <V,E>
  • Steps:
    1. EE 中挑出最小成本的邊 (u,v)(u,v)
    2. 判斷 (u,v)(u,v) 加入 Spanning Tree SS 中是否會形成 cycle
      • 無 cycle: (u,v)(u,v) 加入 SS
      • 有 cycle: 放棄 (u,v)(u,v)
    3. 重複 1.2. 直到挑出 V1|V| - 1 條邊,或 EE 為空
    4. (可省) 若 SS 中邊數 V1\leq |V| - 1,則 GG 沒有 Spanning Tree
  • 時間複雜度
    • 最多執行 E|E|
      • Delete-min cost edge (u,v)(u,v) from EE
      • 判斷 (u,v)(u,v) 加入 SS 是否造成 cycle
    • Delete-min 若使用 Heap 保存各邊成本,則需要 O(logE)O(\log{|E|})
    • cycle 檢查利用 Disjoint SetUnion, Find 操作,約需要 O(1)O(1)
      • 假設採用 Union-by-Height, Find-with-path-Compression
      • 檢查 Find(u)Find(u)Find(v)Find(v) 的值是否相同 (屬於相同 set 會造成 cycle)
      • (u,v)(u,v) 加入 SS 中: Union(u,v)Union(u,v)
    • 總時間為 E(O(logE)+O(1))=O(ElogE)|E| * (O(\log{|E|}) + O(1)) = O(|E|\log{|E|})
      • E<V2O(ElogV)|E| < |V|^2 \Rightarrow O(|E|\log{|V|})

Prim’s Algorithm

  • 給定一個 connected 無向圖 G=<V,E>,V=1,2,3...,nG = <V,E>, V = 1,2,3...,n,令 U=1U = {1} (代表起始 vertex,可以隨意選擇)
  • Steps:
    1. 挑出最小成本的邊 (u,v)(u,v),其中 $u \in U$ 且 $v \in V-U$
    2. (u,v)(u,v) 加入 SS 中,且將 vvVUV-U 中移入 UU
    3. 重複 1.2. 直到 U=VU=V
  • 時間複雜度
    • use Adjacency Matrix: O(V2)O(|V|^2)
    • use Heap: O(ElogV)O(|E|\log{|V|})
    • use Fibonacci Heap: O(VlogV+E)O(|V|\log{|V| + E})

Sollin’s Algorithm

  • 一開始把每個頂點視為一個獨立的樹之 Root
  • Steps:
    1. 從每棵樹中挑出最小成本之 Tree edge
    2. 刪除重複挑出的邊,只保留一份
    3. 重複 1.2. 直到只剩下一棵樹

最短路徑問題

Dijkstra’s Algo Bellmen-Ford Algo Floyd-Warshall Algo
解決問題 單源最短路徑 單源最短路徑 全域最短路徑
策略 Greedy DP DP
Time O(V2)O(V^2) O(V3)O(V^3) O(V3)O(V^3)
圖是否可有負邊 不可
圖是否可有負 cycle 不可 不可 不可

Dijkstra’s Algorithm

  • 給定一個 有向圖 G=<V,E>, V=nG = <V,E>,~|V| = n,,其邊上附有cost (length) 值
  • 使用的資料結構
    • Cost Matrix: 一個 nnn * n 的 Matrix,其中 Cost[i,j]=Cost[i,j] =
      • 邊成本值, if<i,j>E,~if <i,j> \in E
      • 邊成本值, if i=j,~if~i = j
      • 邊成本值, if<i,j>E,~if <i,j> \notin E
    • S: [1,2,...,n]S:~[1,2,...,n] of Boolen,其中 S[i]=S[i]=
      • False (0): 起點到 ii 點之最短路徑尚未確定
      • True (1): 起點到 ii 點之最短路徑已確定
      • 初值皆為 False
    • Dist: [1,2,...,n]Dist:~[1,2,...,n] of Int,其中 Dist[i]=Dist[i]=
      • 起點到 ii 點之最短路徑長
      • 初值為 Cost Matrix 中起點那一列元素值
  • Steps:
    1. 尚未確定最短路徑的點 (S[i]==0S[i] == 0) 中,挑出 Dist 最小的點,令其為 uu,並設定 S[u]=1S[u] = 1
    2. 對於 uu 的所有相鄰點 ww,如果 $S[w] == 0 $,則檢查是否可以優化其 Dist (Relax) (經過 uu 到達 ww 距離更短)
    3. 重複 1.2. n2n - 2
  • 重要假設條件: 無負邊,否則可能無法求出正確值
  • 可以額外建立一個 array 儲存各點之 parent,方便回推最短路徑
  • 時間複雜度 [Algo]
    • use Heap: O(ElogV)O(|E|\log{|V|})
    • use Fibonacci Heap: O(VlogV+E)O(|V|\log{|V| + E})
    • Prim's Algorithm 相同: Base on BFS concept

Bellmen-Ford Algorithm

  • 給定一個 有向圖 G=<V,E>, V=nG = <V,E>,~|V| = n,,其邊上附有cost (length) 值
  • 定義: DistK: [1,2,...,n]Dist^K:~[1,2,...,n] of Int,其中 DistK[i]=Dist^K[i]=
    • 起點到 ii 點之最短路徑長 且經過的邊數 K\leq K
    • Dist1Dist^1 為初值,數值為 Cost Matrix 中起點那一列元素值
  • Steps:
    • 依序求出 Dist2,Dist3...Distn1Dist^2,Dist^3...Dist^{n - 1}Distn1Dist^{n - 1} 即為結果
      • 針對 DistK[i]Dist^K[i],對每個指向 ii 的邊進行檢查是否能 Relax
  • 時間複雜度
    • O(V3)O(|V|^3)
    • O(VE)O(|V| * |E|) [Algo]
  • 檢查是否有 負 cycle
    • 跑完正常的 Bellmen-Ford Algo (n - 1 輪)
    • 再跑一輪,如果有 Distn[i]Dist^n[i] 可以 Relax,則存在 負 cycle

Floyd-Warshall Algorithm

  • 給定一個 有向圖 G=<V,E>,V=1,2,3...,nG = <V,E>, V = 1,2,3...,n
  • 定義: AKA^K: 一個 nnn * n 的 Matrix,其中 AK[i,j]=A^K[i,j]=
    • iijj最短路徑長,且途中經過的頂點編號必須 K\leq K
    • A0A^0 為初值,同 Cost Matrix
  • Steps:
    • 依序求出 A1,A2...AnA^1,A^2...A^nAnA^n 即為結果
      • 針對 AK[i,j]A^K[i,j],進行檢查是否能 Relax (ij or ikji\rightarrow j~or~i\rightarrow k\rightarrow j)
  • 時間複雜度
    • O(V3)O(|V|^3)

A+, AA^+,~A^* 矩陣

  • 給定一個 有向圖 G=<V,E>, V=nG = <V,E>,~|V| = n
  • A+A^+ 矩陣: Transitive Closure Matrix
    • 一個 nnn * n 的 Matrix,其中 A+[i,j]=A^+[i,j]=
      • 1, if1,~if iijj 有 path,且長度 1\geq 1
      • 0, otherwise0,~otherwise
  • AA^* 矩陣: Reflexive-Closure Matrix
    • 一個 nnn * n 的 Matrix,其中 A+[i,j]=A*+[i,j]=
      • 1, if1,~if iijj 有 path,且長度 0\geq 0
      • 0, otherwise0,~otherwise
  • A=A+IA^* = A^+ \cup I (單位矩陣)

AOV Network & Topological sort

AOV (Activity On Vertex) Network

  • 給定一個 有向圖 G=<V,E>G = <V,E>,代表 AOV Network,其中:
    • Vertex: 代表工作 (Activity)
    • Edge: 代表工作執行之先後順序
      • iji \rightarrow j 存在代表 ii 必須先於 jj 執行
  • 用於判斷計畫工作間的執行是否合理,即至少要有 1\geq 1 組合理的工作順序 (Topological sort)

Topological sort

  • 給予一個不具 cycleAOV Network,則至少可以產生 1\geq 1 組合理的頂點拜訪順序,滿足:
    • AOV Network 中,若 ii 有 path 到達 jj,則在此順序中, ii 必定出現在 jj 之前
  • Steps:
    1. 找出 In-degree == 0 之 Vertex ii
    2. 輸出 ii 且刪除從 ii 射出的邊
    3. 重複 1.2. 直到所有點都已經輸出,或是沒有 In-degree == 0 之 Vertex
      • 如果不是所有點皆已經輸出,則無 Topological sort (cycle 存在)
  • Steps [Algo]: 進行 DFS,根據 Vertex Finish 的時間由後往前排序

AOE Network & critical path & critical task

AOE (Activity On Edge) Network

  • 給定一個 有向圖 G=<V,E>G = <V,E>,代表 AOE Network,其中:
    • Vertex: 代表事件 (Event)
    • Edge: 代表工作 (Activity)
    • Edge 上數字: 代表工作完工所需天數
  • 意義:
    • 所有射入事件 Vertex 之工作皆完成後,事件才會發生
    • 事件發生後,從該 Vertex 射出之工作才可以開工
  • 用於計畫之專案管理
  • 求完成計畫之最短天數: critical path 之長度
    • startend 之最長路徑長
    • critical path 可能有多條
    • critical task 上的所有工作
  • 要加速哪些工作可以有效縮短計畫完工天數:
    • 所有 critical path 上的交集 (共同) 工作
  • 哪些工作可以 delay,又可以 delay 多久不影響進度
    • 不在 critical path 上的工作皆可 delay
    • delay 時間:
      • 先求各事件之最早發生時間: start 到各點之最長路徑長
      • 再求各事件之最晚發生時間: 從 end 往回推各點
      • 求各工作之最早開工 (前一事件的最早發生時間)、最晚開工時間 (後一事件的最晚發生時間),根據兩者之差距求得

Articulation Point

  • 在一個 connected 無向圖 中,若刪除某頂點及其連結的邊,則剩下的圖變為 unconnected,該點稱之為 Articulation Point
  • Biconnected Graph:
    • 一個不具有 Articulation Pointconnected 無向圖
  • Biconnected Component:
    • 給定一個 connected 無向圖 G=<V,E>G = <V,E>,令 GG'GG 的一個子圖,且滿足:
      • GG'Biconnected Graph
      • GG'Max Component (沒有其他 Biconnected Graph 子圖可包含 GG')
  • Articulation Point:
    • 從某點開始做 DFS,求各點之 dfn (DFS Number: 拜訪順序)
    • 畫出 DFS Spanning Tree 且標示出 Back edge
    • 求出各點之 low 值:
      • low(x)=min(dfn(x),{dfn(y)  y 為 x 的後代 (含 x) 中最多經過一條 Back edge 所到之點})low(x) = min(dfn(x), \{dfn(y)~|~y~為~x~的後代~(含~x)~中最多經過一條~Back~edge~所到之點\})
    • 判斷規則:
      • 對於 root,若其有 2\geq 2 個子點,則為 Articulation Point,否則不是
      • 對於 非 root 頂點 xx,令 yyxx 之任一子點,若存在 low(y)dfn(x)low(y) \geq dfn(x)xxArticulation Point