Slide 1

Slide 1 text

部分永続Union Find camypaper

Slide 2

Slide 2 text

問題1 • N 頂点の無向グラフがある • Q 個のクエリを処理せよ – u, v をつなぐ辺を追加 – u, v が同じ連結成分に含まれるか判定 • Union Findするだけ

Slide 3

Slide 3 text

問題2 • N 頂点の無向グラフがある • Q 個のクエリを処理せよ – u, v をつなぐ辺を追加 – i 番目のクエリを処理した時点において u, v が同じ連結成分に含まれるか判定 • クエリ先読みして,Union Findするだけ

Slide 4

Slide 4 text

問題3(本題) • N 頂点の無向グラフがある • Q 個のクエリをオンラインで処理せよ – u, v をつなぐ辺を追加 – i 番目のクエリを処理した時点において u, v が同じ連結成分に含まれるか判定 • クエリ先読みできない… • どうする?

Slide 5

Slide 5 text

部分永続Union Find

Slide 6

Slide 6 text

機能 • unite(u, v) – 頂点 u, v が含まれる連結成分を連結する • find(u, t) – t 番目のクエリを処理した時点における 頂点 u が含まれる連結成分の根を求める • Union Findの実装はrankによる unite: O(logN), find: O(logN) のやつを ベースにすることにする(経路圧縮なし)

Slide 7

Slide 7 text

実装(1)全部愚直に持つ • 表のi 行 j 列目は,i 番目のクエリを処理し た時点での,頂点 j の親を表す 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 ??? ??? ??? ??? ??? 2 ??? ??? ??? ??? ??? 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 8

Slide 8 text

実装(1)全部愚直に持つ • 0番目のクエリ: 初期状態 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 ??? ??? ??? ??? ??? 2 ??? ??? ??? ??? ??? 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 9

Slide 9 text

実装(1)全部愚直に持つ • 1番目のクエリ: 1, 3 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 2 1 4 5 2 ??? ??? ??? ??? ??? 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 10

Slide 10 text

実装(1)全部愚直に持つ • 2番目のクエリ: 3, 5 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 2 1 4 5 2 1 2 1 4 1 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 11

Slide 11 text

実装(1)全部愚直に持つ • 3番目のクエリ: 1, 5 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 2 1 4 5 2 1 2 1 4 1 3 1 2 1 4 1 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 12

Slide 12 text

実装(1)全部愚直に持つ • 4番目のクエリ: 2, 4 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 2 1 4 5 2 1 2 1 4 1 3 1 2 1 4 1 4 1 2 1 2 1 5 ??? ??? ??? ??? ???

Slide 13

Slide 13 text

実装(1)全部愚直に持つ • 5番目のクエリ: 4, 5 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 2 1 4 5 2 1 2 1 4 1 3 1 2 1 4 1 4 1 2 1 2 1 5 1 1 1 2 1

Slide 14

Slide 14 text

実装(1)まとめ • この表の行にそってfindをすればO(logN)で findができる! • 空間 O(NQ) は使い物にならない 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 2 1 4 5 2 1 2 1 4 1 3 1 2 1 4 1 4 1 2 1 2 1 5 1 1 1 2 1

Slide 15

Slide 15 text

実装(2)使ったところだけ記録 • 0番目のクエリ: 初期状態 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 ??? ??? ??? ??? ??? 2 ??? ??? ??? ??? ??? 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 16

Slide 16 text

実装(2)使ったところだけ記録 • 1番目のクエリ: 1, 3 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 ??? ??? ??? ??? ??? 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 17

Slide 17 text

実装(2)使ったところだけ記録 • 2番目のクエリ: 3, 5 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 18

Slide 18 text

実装(2)使ったところだけ記録 • 3番目のクエリ: 1, 5 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???

Slide 19

Slide 19 text

実装(2)使ったところだけ記録 • 4番目のクエリ: 2, 4 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 ??? ??? ??? ??? ???

Slide 20

Slide 20 text

実装(2)使ったところだけ記録 • 5番目のクエリ: 4, 5 をつなぐ 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1

Slide 21

Slide 21 text

表をぐっとにらむと • 1番目のクエリ以降,各クエリにつき 定数個の要素しか更新しない – 経路圧縮なしのUnion Findだから当たり前 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1

Slide 22

Slide 22 text

表をぐっとにらむと • 一度でも連結成分の親でなくなった頂点 は二度と連結時に親にならない – 表の赤以降の時点で親になることはない 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1

Slide 23

Slide 23 text

Find(u, t): O(logN) • find(u, t)について以下のように動作させる – u が時刻 t 以降において,親でないとき • find(u の親, t) を返す – そうでないとき • u を返す 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1

Slide 24

Slide 24 text

Find(u, t): O(logN) • find(u, t)について以下のように動作させる – u が時刻 t 以降において,親でないとき • find(u の親, t) を返す – そうでないとき • u を返す 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1 これは,各列の末尾 (黃セル)だけ見ればOK O(1)で判定可能 rankベースのUnion Find なのでO(logN)回しか 呼ばれない

Slide 25

Slide 25 text

Find(u, t): O(logN) • find(u, t)について以下のように動作させる – u が時刻 t 以降において,親でないとき • find(u の親, t) を返す – そうでないとき • u を返す • 例: find(4, 4) – 時刻 4において 親でない – find(2, 4) • 時刻4において親 これは,各列の末尾 (黃セル)だけ見ればOK O(1)で判定可能 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1 rankベースのUnion Find なのでO(logN)回しか 呼ばれない

Slide 26

Slide 26 text

Unite(u, v): O(logN) • i 番目のクエリの時点で – find(u, i), find(v, i) して根を探す – rank実装のUnion Findの要領で表を埋める • find部分が一番重くO(logN) 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 ??? ??? ??? ??? ???

Slide 27

Slide 27 text

実装(2) まとめ • 更新されたところだけ覚えておけばいい • find: O(logN), unite: O(logN)が実現できた

Slide 28

Slide 28 text

応用編

Slide 29

Slide 29 text

問題4 • N 頂点の無向グラフがある • Q 個のクエリをオンラインで処理せよ – u, v をつなぐ辺を追加 – i 番目のクエリを処理した時点における u を含む連結成分のサイズを出力

Slide 30

Slide 30 text

機能 • unite(u, v) – 頂点 u, v が含まれる連結成分を連結する • find(u, t) – t 番目のクエリを処理した時点における 頂点 u が含まれる連結成分の根を求める • size(u, t) – t 番目のクエリを処理した時点における 頂点 u が含まれる連結成分のサイズを求める

Slide 31

Slide 31 text

実装 • 表で持つ情報をちょっと変える – 今まで:親の番号だけ持たせていた 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1 頂点番号 1 2 3 4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 2 2 5 1 1

Slide 32

Slide 32 text

実装 • 表で持つ情報をちょっと変える – 緑字: 連結成分のサイズ – 赤字:親である頂点の番号 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1

Slide 33

Slide 33 text

Find(u, t): O(logN) • find(u, t)について以下のように動作させる – u が時刻 t 以降において,親でないとき • find(u の親, t) を返す – そうでないとき • u を返す 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1

Slide 34

Slide 34 text

Find(u, t): O(logN) • find(u, t)について以下のように動作させる – u が時刻 t 以降において,親でないとき • find(u の親, t) を返す – そうでないとき • u を返す これは,各列の末尾 (黃セル)だけ見ればOK O(1)で判定可能 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1 rankベースのUnion Find なのでO(logN)回しか 呼ばれない

Slide 35

Slide 35 text

• find(u, t)について以下のように動作させる – u が時刻 t 以降において,親でないとき • find(u の親, t) を返す – そうでないとき • u を返す • 例: find(4, 4) – 時刻 4において 親でない – find(2, 4) • 時刻4において親 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1 Find(u, t): O(logN) これは,各列の末尾 (黃セル)だけ見ればOK O(1)で判定可能 rankベースのUnion Find なのでO(logN)回しか 呼ばれない

Slide 36

Slide 36 text

• size(u, t)について以下のように動作させる – find(u, t)して根 v を探す – v について,時刻 t 以前における連結成分の サイズが保存された位置を二分探索で求める • 例: size(4, 4) – 親 v は頂点 2 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1 Size(u, t): O(logN)

Slide 37

Slide 37 text

• size(u, t)について以下のように動作させる – find(u, t)して根 v を探す – v について,時刻 t 以前における連結成分の サイズが保存された位置を二分探索で求める • 例: size(4, 4) – 親 v は頂点 2 – 二分探索すると 時刻4でサイズが 2になったことが わかる 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1 Size(u, t): O(logN)

Slide 38

Slide 38 text

• size(u, t)について以下のように動作させる – find(u, t)して根 v を探す – v について,時刻 t 以前における連結成分の サイズが保存された位置を二分探索で求める • 例: size(4, 4) – 親 v は頂点 2 – 二分探索すると 時刻4でサイズが 2になったことが わかる 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 5 1 Size(u, t): O(logN) find(u, t)はO(logN) 1回の二分探索でO(logN)

Slide 39

Slide 39 text

Unite(u, v): O(logN) • i 番目のクエリの時点で – find(u, i), find(v, i) して根を探す – rank実装のUnion Findの要領で表を埋める – 新しい親は連結成分のサイズを,子側は 親の番号を記録 頂点番号 1 2 3 4 5 クエリ番号 0 1 1 1 1 1 1 2 1 2 3 1 3 4 2 2 5 ??? ??? ??? ??? ???

Slide 40

Slide 40 text

まとめ • find, size, uniteがいずれも O(logN) で可能な 部分永続Union Findができた – (必ずしも同じように実装しなくても達成可能)

Slide 41

Slide 41 text

解ける問題 • AGC002 D: Stamp Rally • yukicoder No. 416: 旅行会社 • CodeFesitival 2016 Elimination Tournament Round 1 A: グラフ • etc.