• 沒有找到結果。

Heap/BFS/Basic Graph

N/A
N/A
Protected

Academic year: 2022

Share "Heap/BFS/Basic Graph"

Copied!
69
0
0

加載中.... (立即查看全文)

全文

(1)

Heap/BFS/Basic Graph

2022/03/17

Lecture By luckyanthonyan

Credit by qazwsxedcrfvtg14,zolution

(2)

Before We Start

• 最後一小時是練習時間&討論時間

• 有些內容競賽上比較不會用到

(3)

Heap

(4)

課程影片

• 看了嗎?

• Q&A

(5)

Why Heap

• 我們為甚麼需要heap?

- 我們想要知道一堆數字當中的最大(最小)值 - 數字會變多變少

• 我們想要能合併兩個heap

- 為了能合併兩堆數字

(6)

Heap 小知識

世界上的Heap有很多種

• 影片中介紹的Binary heap

• Binomial heap

• Pairing heap

• Thin heap

• Fibonacci heap

• ……

(7)

Heap 小知識

https://en.wikipedia.org/wiki/Heap_(data_structure)#Comparison_of_theoretic_bounds_for_variant s

(8)

Heap 小知識

• 為什麼會有這麼多種Heap?

• 有的常數比較小

• 有的可以O(1)插入

• 有的可以O(1)刪除

• 有的可以O(logN)合併??

• 有的可以O(1)合併??!!

• 因為礙於篇幅,有興趣請自行上網查詢資料:P

(9)

Heap 基本操作

(10)

priority_queue

• std::priority_queue

• push:將一個元素放入priority_queue中

• top:詢問現在priority_queue中權重最大的元素

• pop:將priority_queue中權重最大的元素拿掉

(11)

時間複雜度

• push:O(logN)

• top:O(1)

• pop:O(logN)

(12)

Heap push

(13)

heap

• heap其實就是一棵complete binary tree

• 因為是complete binary tree所以我們能穩定的控制層數

6 5

2 1

3

(14)

heap

• heap性質:父節點的權重不小於子節點的權重

6 5

2 1

3

(15)

heap

6 5

2 1

3 push 4

(16)

heap

• 將元素放進tree:O(1) 6

5

2 1

3

4

push 4

(17)

heap

• 將元素放進tree:O(1)

• 和父節點比較:O(1) 6

5

2 1

3

4

push 4

(18)

heap

• 將元素放進tree:O(1)

• 和父節點比較:O(1)*log(n)

• 一直往上浮,直到權重不大於父節點,最多比較log(n)次 6

5

2 1

4

3

push 4

(19)

heap

• 將元素放進tree:O(1)

• 和父節點比較:O(1)*log(n)

• 一直往上浮,直到權重不大於父節點,最多比較log(n)次

• 整體來看:O(log(n)) 6

5

2 1

4

3

push 4

(20)

heap

• root的權重一定最大,O(1) 6

5

2 1

4

3

top

(21)

heap

6 5

2 1

4

3

pop

(22)

heap

• root的權重最大,pop掉 5

2 1

4

3

pop

(23)

heap

• root的權重最大,pop掉

• 比較兩個子節點,權重大的往上浮:O(1) 5

2 1

4

3

pop

(24)

heap

• root的權重最大,pop掉

• 比較兩個子節點,權重大的往上浮:O(1)*log(n)

• 繼續比,最多比log(n)次 5

2 1

4

3

pop

(25)

heap

• root的權重最大,pop掉

• 比較兩個子節點,權重大的往上浮:O(1)*log(n)

• 繼續比,最多比log(n)次

• 最後空位用最後一個元素補 5

2

1

4

3

pop

(26)

heap

• root的權重最大,pop掉

• 比較兩個子節點,權重大的往上浮:O(1)*log(n)

• 繼續比,最多比log(n)次

• 最後空位用最後一個元素補

• 補上後可能權重又比父親大,還要往上浮一次 5

2

3 1

4 pop

(27)

heap

• root的權重最大,pop掉 5

2 1

4

3

pop

(28)

heap

• root的權重最大,pop掉

• 將最後一個元素放到root 3

5

2 1

4 pop

(29)

heap

• root的權重最大,pop掉

• 將最後一個元素放到root

• 和兩個子節點中權重較大的節點比較:O(1) 3

5

2 1

4 pop

(30)

heap

• root的權重最大,pop掉

• 將最後一個元素放到root

• 和兩個子節點中權重較大的節點比較:O(1)*log(n)

• 一直下沉直到權重不小於兩個子節點,最多比較log(n)次 5

3

2 1

4 pop

(31)

heap

• root的權重最大,pop掉

• 將最後一個元素放到root

• 和兩個子節點中權重較大的節點比較:O(1)*log(n)

• 一直下沉直到權重不小於兩個子節點,最多比較log(n)次

• 整體來看:O(log(n)) 5

3

2 1

4 pop

(32)

Heap Magic

(33)

魔法

• 幾個在C++中關於Heap的魔法

• STL

• std::priority_queue

• 黑魔法

• __gnu_pbds::priority_queue

(34)

std::priority_queue

• #include <queue>

• std::priority_queue<int> pque;

• priority_queue<int, vector<int>, greater<int> > lque

(35)

__gnu_pbds::priority_queue

• #include <ext/pb_ds/priority_queue.hpp>

• __gnu_pbds::priority_queue<int> pque;

• priority_queue<int, greater<int> > lque

• h1.join(h2); //合併h1,h2兩個heap

• pbds heap可以選擇要用哪種heap(改tag)

有一些教學:https://emiliatancoding.blogspot.com/2019/05/pbds-priorityqueue.html

(36)

Building Heap

• 如果一開始就已經有所有元素了,要建造出一個Heap

• Insertion of Heap: O(logN)

• 所以Build a heap of N element: O(NlogN)

• 其實這個bound不夠緊,可以壓到O(N)

https://www.geeksforgeeks.org/time-complexity-of-building-a-heap/

(37)

Heap Problemset

(38)

Problemset

• 只給網址,有些人不喜歡被暴雷

https://zerojudge.tw/ShowProblem?problemid=b606

https://tioj.ck.tp.edu.tw/problems/1911

https://tioj.ck.tp.edu.tw/problems/2026

(39)

Flood fill

(40)

課程影片

• Q&A

(41)

淹水

• 模擬「淹水」的過程很麻煩,幾個方向就要寫幾個很大串的 if,

怎麼辦?

• if (x+1 < n) go(x+1,y);

• if (y+1 < m) go(x,y+1);

• if (x-1 >=0) go(x-1,y);

• if (y-1 >=0) go(x,y-1);

• 提示:有沒有發現所有的 if 其實都長得很像?

(42)

淹水

把x,y的變動量拿出來:

(x+1 , y+0) (x-1 , y+0) (x+0 , y+1) (x+0 , y-1)

int dx[]={+1,-1,+0,+0};

int dy[]={+0,+0,+1,-1};

(43)

淹水

把x,y的變動量拿出來:

(x+1 , y+0) (x-1 , y+0) (x+0 , y+1) (x+0 , y-1)

int dx[]={+1,-1,+0,+0};

int dy[]={+0,+0,+1,-1};

(44)

BFS code

for(int i=0;i<4;i++){

int next_x = x + dx[i];

int next_y = y + dy[i];

if(check(next_x,next_y)){

queue.push(next_x , next_y);

} }

(45)

DFS 跟 BFS 的差異

• 我想要從迷宮的起點走到終點

• BFS?

• DFS?

• 我想要用最短路從迷宮的起點走到終點

• BFS?

• DFS?

(46)

DFS 跟 BFS 的差異

• 我想要從迷宮的起點走到終點

• BFS?

• DFS?

• 我想要用最短路從迷宮的起點走到終點

• BFS?

• DFS?

• DFS沒辦法得到最短路徑

(47)

BFS & DFS

• DFS

• Graph traversal

• BFS

• Graph traversal

• Flood-fill

• Unweighted-Graph shortest path

(48)

Problemset

給想做額外練習的同學 題目都不難

• https://zerojudge.tw/ShowProblem?problemid=a597

https://tioj.ck.tp.edu.tw/problems/1085

https://codeforces.com/problemset/problem/598/D

(49)

Graph

(50)

課程影片

• Q&A

(51)

存圖

• 相鄰串列

• 相鄰矩陣

(52)

比較

• 相鄰矩陣

• 空間複雜度:O(V2)

• 查詢兩個點之間是否有邊:O(1)

• 遍歷一個點v周圍的邊:O(V)

• 增加一條邊:O(1)

• 刪除一條邊:O(1)

• 相鄰串列

• 空間複雜度:O(V+E)

• 查詢兩個點之間是否有邊:O(degree(V))

• 遍歷一個點v周圍的邊:O(degree(V))

• 增加一條邊:O(1)

• 刪除一條邊:O(degree(V))

(53)

想想看-是否有環?

• 給你一張有向圖,要怎麼知道這張圖上面有沒有環?

• DFS?

• BFS?

(54)

有向無環圖

• 現在有一個工廠,裡面有很多台機器,有些機器所生產 的東西可能會依賴於其他機器,但是保證不會循環。

• 問:找出一個機器的執行順序使得過程中不會有機器依賴 於還沒執行過的機器。

• 拓樸排序!

(55)

• 有向無環圖(

DAG

)

有向無環圖

(56)

• A、G 可以先處理,因為入度為 0

有向無環圖

(57)

B 入度為 0,接著處理 B

有向無環圖

(58)

Problemset

• 一道簡單的練習題

• https://zerojudge.tw/ShowProblem?problemid=a454

(59)

隱式圖搜索

(60)

隱式圖搜索

• 有時候我們有狀態 但並不知道整張圖的全貌

• 甚至有可能圖很大張

• 用DFS會TLE

• 所以我們用BFS尋找答案

(61)

量杯問題

• 給你 𝑛 (1 ≤ 𝑛 ≤ 5) 個量杯,第 𝑖 個量杯的容量式 𝑚𝑖 的水

• 問你倒出剛好 𝑡 的水,最少要幾個步驟

• 一開始所有量杯都是空的

(62)

量杯問題

• 設定 BFS 的狀態

• 在queue裡面放 Hash_table

• 把所有量杯的當前狀態壓進一個long long

• 題目沒有明確地給出「邊」,但還是能 BFS

• 把某些不可能的case先特判掉,避免浪費時間

• 目標容量大於所有量杯的容量

• 即 𝑡 > max

1≤𝑖<=𝑛 𝑚𝑖

• 目標容量不是滿水容量最大公因數的倍數

• 即 𝑡/ (gcd

1≤𝑖≤𝑛

𝑚𝑖) ≠ 0

(63)

量杯問題

• 想不到case要判甚麼但就是 TLE 了QQ

• 時間剪枝(x

(64)

練習一下

(65)

練習一下

• 有一張 N 點 M 邊無向無權圖,有兩個人在 S ,他們分別要走到A、B

• 他們一定要走最短路到達自己的目的地

• 他們想要能一起走越多的路越好

• 請問他們最多能一起經過多少點

(66)

練習一下

• 答案滿足以下條件:

• 設 𝑑𝑖𝑠() 為兩點之間的最短距離

• 設 𝑋 是圖上的某個點

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐴) = 𝑑𝑖𝑠(𝑆 → 𝐴)

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐵) = 𝑑𝑖𝑠(𝑆 → 𝐵)

• 對所有滿足條件的點 𝑋 ,取最大的 𝑑𝑖𝑠(𝑆 → 𝑋) 即可

(67)

練習一下

• 答案滿足以下條件:

• 設 𝑑𝑖𝑠() 為兩點之間的最短距離

• 設 𝑋 是圖上的某個點

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐴) = 𝑑𝑖𝑠(𝑆 → 𝐴)

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐵) = 𝑑𝑖𝑠(𝑆 → 𝐵)

• 需要好多最短路

• 對每個點做一次 𝐵𝐹𝑆:𝑂(𝑁 × (𝑁 + 𝑀))

(68)

練習一下

• 答案滿足以下條件:

• 設 𝑑𝑖𝑠() 為兩點之間的最短距離

• 設 𝑋 是圖上的某個點

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐴) = 𝑑𝑖𝑠(𝑆 → 𝐴)

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐵) = 𝑑𝑖𝑠(𝑆 → 𝐵)

• 需要好多最短路

• 對每個點做一次 𝐵𝐹𝑆:𝑂(𝑁 × (𝑁 + 𝑀))

• 對 𝑆、𝐴、𝐵 各做一次 𝐵𝐹𝑆 : 𝑂 𝑁 + 𝑀

(69)

練習一下

• 答案滿足以下條件:

• 設 𝑑𝑖𝑠() 為兩點之間的最短距離

• 設 𝑋 是圖上的某個點

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐴) = 𝑑𝑖𝑠(𝑆 → 𝐴)

• 𝑑𝑖𝑠(𝑆 → 𝑋) + 𝑑𝑖𝑠(𝑋 → 𝐵) = 𝑑𝑖𝑠(𝑆 → 𝐵)

• 需要好多最短路

• 對每個點做一次 𝐵𝐹𝑆:𝑂(𝑁 × (𝑁 + 𝑀))

• 對 𝑆、𝐴、𝐵 各做一次 𝐵𝐹𝑆 : 𝑂 𝑁 + 𝑀

• https://csacademy.com/contest/archive/task/long_journey

參考文獻

相關文件

大きく違う点は、従来の BASIC ではプログラムの実行順序はプログラム作成時に予め決 めたとおりに実行する定義型であるの対し、Visual

pop

• vertex

Credit to Theory of Computer Games, 2018 Fall.. Normal BFS

Credit to Theory of Computer Games,

Credit to Theory of Computer Games, 2018 Fall.. Normal BFS

紅色 : 當今在的 Heap 被使用為合併後的 Heap...

課堂補充 by qazwsxedcrfvtg14...