# [資料結構] CH17. Advanced Graphs
* 繼續來看更多名詞吧...
## Articulation Point
* 關節點,若該點被移除,整個graph會被分為兩個部分。
* 下圖C、D就是**Articulation Point**。
```graphviz
graph articulation
{
C [color="red"]
D [color="red"]
A -- B
A -- C
B -- D
C -- D
D -- E
D -- F
C -- H
C -- J
C -- I
H -- J
H -- I
J -- I
}
```
## Bi-connected graph
* 雙向連接圖表示沒有任何**articulation point**的graph。
```graphviz
graph BiConnected
{
A--B
B--C
D--C
D--A
{rank=same;A;B}
{rank=same;C;D}
}
```
## Bridge
* 橋梁,若該邊被移除,整個graph會被分為兩個部分。
* 下圖中,e(A,B)和e(B,C)是bridge。
```graphviz
graph Bridge
{
A--B--C--D--E--C
{rank="same";D;E}
}
```
## Representation of Graphs
* 在電腦中儲存graph的方法通常有三種。
### Sequential Representation
* 若有`n`個node在這張圖中,我們就宣告一個`n*n`的二維矩陣來儲存它。
* 元素$a_{i,j}$表示從第$i$個點連到第$j$個點的邊有幾個。
* 下圖(d)為特例,儲存的是該邊的權重而不是邊的數量。
* 可以觀察到以下特性:
* 如果該graph沒有loop,對角線上的數字都會是`0`。
* 如果該graph是無向圖,矩陣會以對角線為軸映射。
* 如果該graph的邊不多,大多數的數字都會是`0`,因此矩陣會成為稀疏矩陣。
* 如果該graph沒有multiple edges,矩陣裡面就只會有`0`或`1`,此時的矩陣又稱做**bit matrix**或是**boolean matrix**。
* 這要畫圖我會畫到死,直接上圖片。
* ![](https://i.imgur.com/jhW8yhY.png)
---
* 將原矩陣寫作$A^1$,$a^1_{i,j}$也可以表示$v_i$到$v_j$長度為`1`的path數量。
* 將$A^1$做平方得到$A^2$,則$a^2_{i,j}$表示$v_i$到$v_j$長度為`2`的path數量。
* $A^3$、$A^4...A^n$,表示長度為`n`的path數量。
* 設`n`為該graph的node數量,$B^{n-1}=A^1+A^2+...+A^{n-1}$,$P_{i,j}=max(B^{n-1}_{i,j},1)$,則矩陣P表示從$v_i$到$v_j$是否存在path。
### Linked Representation
* 使用Linked-List的方法來記錄關係。
* 設立`n`個pointer,將第i個點有連到的邊都串在第i個pointer之後。
* 對於邊很少的時候是好選擇(用上面的矩陣會變成稀疏矩陣、浪費空間)。
* ![](https://i.imgur.com/QdliiVO.png)
### Adjacency Multi-list
* 把每一個邊的資料存起來,再用指標串接關係。
* 資料通常有:
* 第一個點。
* 第二個點。
* 其他第一個點連到的邊。
* 其他第二個點連到的邊。
* 如果沒有其他連到的邊了,或是其他的邊已經被找過了,那就將其設為NULL。
* ![](https://i.imgur.com/05cT9W1.png)
## Traversal Algorithms
* 當我們要遍歷一張graph所有的點時,我們有BFS和DFS兩種方式。
### Breadth-first Search
* 廣度優先搜索,使用**queue**儲存接下來要探索的點。
* 範例:從點A使用BFS找出A到I的最短路徑,優先度為英文字母越小的點先跑(ex:B先C後)。
```graphviz
digraph BFS
{
A->B->E->C->G->I->F->H
A->C
A->D->G
E->F->C
D->C->B
{rank="same";B;C;D;}
{rank="same";E;F;G;}
}
```
* 先跑A,將BCD加入到queue裡面。
* ans: A
* queue: B, C, D
* 從queue裡面pop出下一個要跑的點,跑點B,將E加入到queue裡面。(ori為來源,我們要知道來源才能回推路徑。)
* ans: A, B
* ori: 0, A
* queue: C, D, E
* pop出點C,加入G,B跑過了所以不加。
* ans: A, B, C
* ori: 0, A, A
* queue: D, E ,G
* pop點D,沒有點可以加。
* ans: A, B, C, D
* ori: 0, A, A, A
* queue: E ,G
* pop點E,加入F。
* ans: A, B, C, D, E
* ori: 0, A, A, A, B
* queue: G, F
* pop點G,加入I。
* ans: A, B, C, D, E, G
* ori: 0, A, A, A, B, C
* queue: F, I
* 此時找到目標點I了,往回推是那些點導向它的。
* I是G找到的;G是C找到的;C是A找到的。
* 因此點A到I的最點path為A>C>G>I。
### Depth-first Search
* 深度優先搜索,使用**stack**儲存接下來要探索的點。
* 範例:使用DFS從點H,依順序輸出探索到的點。
```graphviz
digraph BFS
{
A->B->E->C->G->I->F->H->E
A->C
A->D->G
E->F->C
D->C->B
{rank="same";B;C;D;}
{rank="same";E;F;G;}
}
```
* 先跑H,將E加到stack中。
* ans: H
* stack: E
* pop點E,加入CF。
* ans: H, E
* stack: C, F
* pop點F。
* ans: H, F
* stack: C
* pop點C,加入B。
* ans: H, E, F, C
* stack: B
* pop點B,stack沒東西了,結束。
* ans: H, E, F, C, B。
---
* BFS可以找最短路徑、DFS雖然也可以但比較麻煩。
* 這兩種演算法想要練習的話可以自行google經典題目**老鼠走迷宮**。
###### tags: `DS` `note`