--- tags: 圖論, 拓樸排序 Topological order, 最短路徑, 最小生成樹 MST, dfs tree, ap, bridge, scc --- # 圖論 ## 拓樸排序 Topological order ```graphviz digraph topological1{ nodesep=0.5 rankdir = LR; a -> b[color = red]; b -> e[color = orange] a -> d[color = red]; d -> e[color = yellow]; b -> c[color = orange]; c -> e[color = green]; e -> f[color = green]; c -> f[color = blue]; } ``` ### 方法1. 計算 in-degre 1. 將每一點的入度數算出 2. 入度數為0的點push進queue裡面 3. 將queue裡點的點拿出並將邊刪除 4. 刪除邊後的點入度數若為0則push進去queue 5. queue pop的順序為一組topological order 6. 若有結束後有入度數不為0的代表有環 ### 方法2. dfs * dfs未完成前又回到原dfs的點則圖有環 * dfs的過程為ㄧ組topological order --- ## 單源最短路徑 ```graphviz graph shortest_path{ nodesep=1 rankdir = LR; a -- b [label = "1"]; a -- c [label = "2", color = green]; b -- c [label = "4"]; b -- d [label = "7"]; c -- d [label = "4"]; d -- e [label = "1"]; c -- e [label = "3", color = green]; } ``` ### 方法1. Bellman-Ford #### 適用情形: * 有負邊 * 檢測負環 #### **init:** $\qquad$$edges = {(u_1, v_1), (u_2, v_2), (u_3, v_3), ... (u_m, v_m)}$ $\qquad$$d[n]={\infty}, d[start]=0$ #### **solve:** $\qquad$ $for\:vertex=1\sim n:$ $\qquad$$\qquad$$for(u,v)\;in\;edges$ $\qquad$$\qquad$$\qquad$$d[vertex]=min(d[vertex],\:d[vertex]+cost(u,v))$ "鬆弛邊" #### $複雜度O(nm)$ ### 方法2. Dijkstra #### 適用情形: * 無負邊 * 時間限制較緊 #### **init:** $\qquad$$d[n]=\infty,d[start]=0$ #### **solve:** 1. 將start點push進priority queue 2. 將top點依序拿出,連接的點若可更新權重,則更新為d[start]+cost,並push進priority queue 3. priority queue內為空則結束 #### $複雜度O(mlogm)$ --- ## 多源最短路徑 ### Floyd-Warshall #### **solve:** $\qquad for\:k=1\sim n:$ $\qquad\qquad for\ i=1\sim n:$ $\qquad\qquad\qquad for\ j=1\sim n:$ $\qquad\qquad\qquad\qquad dp[i][j]=min(dp[i][j],\ d[i][k]+dp[k][j])$ #### $複雜度O(n^3)$ --- ## 並查集 disjoint-set ```cpp= int Find(int x, vector<int> &parent){ if(parent[x] == x){ return x; } else{ return parent[x] = Find(parent[x], parent); } } void Union(int x, int y, vector<int> &parent){ parent[Find(x, parent)] = Find(y, parent); return; } ``` ### 路徑壓縮 * $parrent[Find(x)] = Find(y)$ * 複雜度:$O(log^*n)$ ### 啟發式合併 union by rank * rank: size of tree --- ## 最小生成樹 MST ```graphviz graph MST{ nodesep=1 rankdir = LR; a -- c [label = "2", color = green]; a -- b [label = "1", color = green]; b -- c [label = "4"]; c -- d [label = "4", color = green]; b -- d [label = "7"]; c -- e [label = "8"]; d -- e [label = "3", color = green]; e -- f [label = "6"]; d -- f [label = "3", color = green]; } ``` ### 方法1. kruskal 1. 將邊的cost由小到大排序 2. 將邊上的點依序Union,若已為同一群則忽略 3. $ans=\sum沒被忽略的邊$ #### $複雜度O(mlogm)$ ### 方法2. prim #### **init:** $\qquad$$d[n]=\infty,d[start]=0$ 1. 隨機挑選start點加入 priority queue 2. 將top點依序拿出,連接的點若可更新權重,則更新為cost,並push進priority queue 3. priority queue內空則完成 4. $ans = \sum_{i=1}^{n}d[n]$ #### $複雜度O(mlogm)$ --- ## dfs tree ```graphviz digraph dfs_tree{ nodesep=0.5 //rankdir = LR; a[color = red] c[color = red] b[color = red] i[color = red] d[color = red] j[color = red] a -> c a -> b[color = orange] b -> e[color = orange] b -> j j -> k j -> l[color = orange] c -> d[color = orange] c -> i d -> f[color = orange] i -> g i -> h[color = orange] i -> a[color = blue] g -> a[color = blue] k -> b[color = blue] } ``` $t(u):進入u的時間$ $low(u):u最多經過一條backedge,可以走到的最小t值$ ### bridge ```graphviz digraph bridge{ v u -> v[label = "bridge", color=orange] } ``` $如果\ low(v)=t(v),\ 則u\rightarrow v為bridge$ ### Articulation Point #### Case1 $點u不是root$ ```graphviz graph case1{ o[label=""] u[color=red] o -- u u -- v } ``` $如果low(v)\ge t(v),\ 則點u為AP$ #### Case2 $點u是root$ ```graphviz graph case2{ u[color=red] u -- v1 u -- v2 } ``` $如果low(v_1)\ge t(v),\ 且low(v_2)\ge t(v),\ 則u為AP$ --- ## 強聯通單元 SCC ```graphviz digraph scc{ nodesep=0.5 rankdir = LR; b -> d b -> e d -> e a -> g b -> g subgraph cluster0{ label="scc1"; color=green; shape=circle; a -> b[color=orange]; b -> c[color=orange]; c -> a[color=orange]; } subgraph cluster1{ color=green label="scc2" d } subgraph cluster3{ color=green label="scc3" e -> f[color=orange] f -> g[color=orange] g -> e[color=orange] } } ``` ### 性質 * 若將每一組scc視作一節點,則此圖必為DAG * $如果sccA\rightarrow sccB$ $則max\{t(a)|a\in A\}>max\{t(b)|a\in B\}$ ---