---
# System prepended metadata

title: 圖論
tags: [' 拓樸排序 Topological order', ' bridge', ' 最短路徑', ' 最小生成樹 MST', 圖論, ' scc', ' dfs tree', ' ap']

---

---
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\}$

---




