WiwiHo
https://hackmd.io/@wiwiho/crc1082algo
https://tg.pe/xgaG
Graph
❌圖片(picture) ⭕圖(graph)
由一些節點和邊組成的東西
記作 \(G=(V,E)\)
連接兩個節點
(undirected edge)
雙向的邊
連接節點 \(u\)、\(v\) 的無向邊
記作 \((u,v)\)、\((v,u)\)
且 \((u,v)=(v,u)\)
i.e. 記作無序對
(directed edge)
單向的邊
從 \(u\) 到 \(v\) 的有向邊
記作 \((u,v)\)
i.e. 記作有序對
邊或點上可能有權重
有就稱為帶權
Note:
畫圖講
Note:
畫圖講
沒有環的連通圖
無根樹上的任何一個節點都可以當作根
變成有根樹
Note:
畫圖講
一個 \(|V| \times |V|\) 的矩陣
記作 \(M\)
\(M_{u,v}\) 是邊 \((u,v)\) 的資訊
e.g. 存不存在、權重
空間複雜度:\(O(|V|^2)\)
時間複雜度:
\(M=\begin{bmatrix} \text{X} & 10 & \text{X} & 2 & 5 \\ 10 & \text{X} & 7 & 3 & \text{X} \\ \text{X} & 7 & \text{X} & \text{X} & \text{X} \\ 2 & 3 & \text{X} & \text{X} & \text{X} \\ 5 & \text{X} & \text{X} & \text{X} & \text{X} \end{bmatrix}\)
Note:
注意無向圖和重邊
開 \(|V|\) 個大小可變的容器
第 \(i\) 個存節點 \(i\) 的鄰邊或出邊資訊
空間複雜度:\(O(|V|+|E|)\)
時間複雜度:
鄰接矩陣:\(O(|V|^2)\)
鄰接串列:\(O(|V|+|E|)\)
Depth-First Search
盡量往深處走
Note:
畫圖講過程
某種遞迴
vector<vector<int>> g; //鄰接串列
vector<bool> vst; //用來記錄每個點走過了沒
void dfs(int now){
vst[now] = true;
//do something
for(int i : g[now]){
if(vst[i]) continue;
dfs(i);
}
//do something
}
呼叫 \(dfs(v)\) \(\Rightarrow\) \(v\) 入堆
\(\Rightarrow\) \(v\) 入點
\(dfs(v)\) 結束 \(\Rightarrow\) \(v\) 出堆
\(\Rightarrow\) \(v\) 出點
入點順序:前序
出點順序:後序
時間複雜度:\(O(|V|+|E|)\)
Breadth-First Search
先把所有知道可以走的點走完
Note:
畫圖講過程
vector<vector<int>> g; //鄰接串列
vector<bool> vst; //某個點有沒有走過或有沒有在 queue 裡
queue<int> q;
q.push(...); //把起點放進去
while(!q.empty()){
int now = q.front();
q.pop();
for(int i : g[now]){
if(vst[i]) continue;
q.push(i);
vst[i] = true;
}
}
Note:
注意 vst
由起點開始擴散
https://www.youtube.com/watch?v=x-VTfcmrLEQ
離起點進的先、離起點遠的後
\(\Rightarrow\) 可以拿來做不帶權圖最短路徑
Note:
畫圖講
時間複雜度:\(O(|V|+|E|)\)
更經典的下一堂課才會講 (?
\(N \times M\) 的二維表格可以視為
有 \(N+M\) 個節點的圖
如果某兩個格子可以互通
那就在它們兩個的節點之間連邊
小技巧:
通常能互通的格子相對位置是固定的
所以直接去看相對位置就好
Note:
這題最短路徑長是含起終點的格子數
不帶權最短路徑
\(\Rightarrow\) BFS
Euler path
一條經過所有的邊
且不經過重複的邊
但可以經過重複的點的路徑
無向圖:
恰有 0 個或 2 個度數是奇數的點
有向圖:
所有點的入度等於出度
或有恰一個點的入度比出度多 1
和恰一個點的出度比入度多 1
對邊 DFS
再把出點順序倒過來
Hamiltonian path
經過所有點恰一次的路徑
(起終點相同不算重複)
位元 DP
Note:
看講義
講旅行推銷員
有時候題目裡不會出現任何關於圖的關鍵字
看起來也沒有類似點、邊的東西
但解法卻和圖論有關
Note:
口頭講作法
Note:
口頭講作法
在樹上最長的簡單路徑
先隨便找一個點 \(u\)
找到離它最遠的點 \(v\)
再找到離 \(v\) 最遠的點 \(w\)
\(v\) 到 \(w\) 的簡單路徑就是樹直徑
兩次 DFS
以它為根時
樹的深度會最小的點
Note:
會在直徑上
把一個節點 \(v\) 從樹上拔掉
出現的連通塊大小都不超過本來點數的一半
\(v\) 就是樹重心
Note:
看講義,口頭講
每個節點最多只有兩個子節點的有根樹
有時候子節點會有左右之分
Note:
講左右子節點、子樹、兄弟節點
Note:
講證明
Note:
看講義講
//l[i]=i的左子節點,r[i]=i的右子節點,-1表示沒有
vector<int> l, r;
void dfs(int now){
//preorder
if(l[i] != -1) dfs(l[i]);
//inorder
if(r[i] != -1) dfs(r[i]);
//postorder
}
Note:
中序性質口頭講
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing