[Data Structure] Graph
- 2023.10.01
- Data Structure Graph Topology
Definition
Undirected Graph
G = (V, E)
V : Vertices 頂點
E : Edges 邊 := (u, v)
Adjacent Vertexs
A vertex u is adjacent to vertex v ⇔ (u, v) ∈ E
Directed Graph|Digraph
G = (V, A)
E : Arcs 邊 := (x, y);
x → y
- x: tail
- y: head
Loop := (x, x)
Walk := (v1, v2, v3, …, vn), ∀ vi, vi + 1 ∈ Walk ⇒ (vi, vi + 1) ∈ E
if v1 != vn ⇒ (v1, v2, v3, …, vn) is a open walk
Trail := (v1, v2, v3, …, vn) is a Walk ∧ if i != j ⇒ (vi, vi + 1) != (vj, vj + 1) (No Repeated Edge in the Trail.)
Path := (v1, v2, v3, …, vn) is a Walk ∧ if i != j ⇒ vi != vj (No Repeated Vertex in the Path.)
Circuit := (v1, v2, v3, …, v1) is a Closed Walk
Cycle / Simple Circuit
(v1, v2, v3, …, vn) is a cycle ⇔ vi == vj ∧ i < j iff i == 1 ∧ j == n
Degree
在 undirected graph 中,degree(v) := v 的 edges 數
Indegree
在 directed graph 中,indegree(v) := 起始於 v 的 edges 數
Outdegree
在 directed graph 中,indegree(v) := 終止於 v 的 edges 數
Internal Vertex / External Vertex / Branch Vertex
- internal vertex / inner vertex) := a vertex of degree at least 2
- external vertex / outer vertex / terminal vertex / leaf (in a tree) := a vertex of degree 1
- branch vertex (in a tree) := vertex of degree at least 3
Connected Component
Strongly Connected Component 強連通元件
指「每一個 vertex 都能由任意 vertex 抵達」的 directed graph
※ 只有一個 vertex 的 graph 也是 SCC
Kosaraju’s Algorithm
⭐️ Tarjan’s Strongly Connected Components Algorithm
Time Complexity: Tarjan’s SCC Algorithm ≅ Path-Based SC Algorithm ≥ Kosaraju’s Algorithm
- v.index 依其被遍歷順序的流水編號
- v.low_link := min([w. index for w in scc(v)])
- 還沒走過的路徑就持續呼叫遞迴函式 strong_connect()
strong_connect() 的開頭會創建 v.index 和 v.low_link - 當走到了先前走過的 vi
由於先前走過的 vi 預設的 vi.low_link == vi.index 比較小
藉此更新走到 vi 前的最後一個 vj.low_link ← vi.index - 之後遞迴函式 strong_connect() 會開始逐層的結束
結束之後會把相應的 vk.low_link 更新為 vj.low_link == vi.index - 回到 vi 時,會從 stack 中將 vi ~ vk pop 出來作為新的 SCC
- 不符合上述行為的 vertex 會自己作為一個新的 SCC
以
D → A → B
↑ ↙︎
C
為例:
- A – 新增 A(0, 0)
→ B – 新增 B(1, 1)
→ C – 新增 C(2, 2)
⇒ A – A 在 stack 中 ⇒ 修正 C(2,
20)
⇒ 以 C 的 low_link 修正 B(1,
10)
⇒ A 的 index == low_link ⇒ 新增 SCC1 {A, B, C}
- B – 略過 (已存在且已歸類為 SCC1 不在 stack 中)
- C – 略過
- D – 新增 D(3, 3)
⇒ A – 略過
⇒ D 的 index == low_link ⇒ 新增 SCC2 {D}
def tarjan(vertexes, edges): """ Args: vertexes := [v_1, v_2, ...] edges := {v_1: [w_11, w_12, ...], v_2: [w_21, w_22, ...], ...} """ index = -1 s = [] # stack vertexes = {v: {"index": None, "low_link": None, # low_link := the minimum index in scc "on_stack": False} for v in vertexes} sccs = set() def strong_connect(v): nonlocal index, s, vertexes, sccs vertexes[v]["index"] = vertexes[v]["low_link"] = (index := index + 1) s.append(v) vertexes[v]["on_stack"] = True # compute v.low_link for w in edges[v]: if vertexes[w]["index"] is None: # not traversed yet strong_connect(w) vertexes[v]["low_link"] = min(vertexes[v]["low_link"], vertexes[w]["low_link"]) elif vertexes[w]["on_stack"]: # still in the stack, not categorized into scc yet vertexes[v]["low_link"] = min(vertexes[v]["low_link"], vertexes[w]["index"]) if vertexes[v]["index"] == vertexes[v]["low_link"]: scc = [] while s: w = s.pop() vertexes[w]["on_stack"] = False scc.append(w) if w == v: break sccs.add(frozenset(scc)) for v in vertexes: if vertexes[v]["index"] is None: strong_connect(v) return sccs
Path-Based Strong Component Algorithm (Gabow’s Algorithm)
Problems
- Leetcode # 210. Course Schedule II
- Leetcode # 1615. Maximal Network Rank
- Leetcode # 2846. Minimum Edge Weight Equilibrium Queries in a Tree
Last Updated on 2023/10/04 by A1go