Upgrade to Pro — share decks privately, control downloads, hide ads and more …

部分永続 Union Find / persistent_dsu

camypaper
November 07, 2017
3.4k

部分永続 Union Find / persistent_dsu

camypaper

November 07, 2017
Tweet

Transcript

  1. 問題1 • N 頂点の無向グラフがある • Q 個のクエリを処理せよ – u, v

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

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

    をつなぐ辺を追加 – i 番目のクエリを処理した時点において u, v が同じ連結成分に含まれるか判定 • クエリ先読みできない… • どうする?
  4. 機能 • unite(u, v) – 頂点 u, v が含まれる連結成分を連結する •

    find(u, t) – t 番目のクエリを処理した時点における 頂点 u が含まれる連結成分の根を求める • Union Findの実装はrankによる unite: O(logN), find: O(logN) のやつを ベースにすることにする(経路圧縮なし)
  5. 実装(1)全部愚直に持つ • 表のi 行 j 列目は,i 番目のクエリを処理し た時点での,頂点 j の親を表す

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

    クエリ番号 0 1 2 3 4 5 1 ??? ??? ??? ??? ??? 2 ??? ??? ??? ??? ??? 3 ??? ??? ??? ??? ??? 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???
  7. 実装(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 ??? ??? ??? ??? ???
  8. 実装(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 ??? ??? ??? ??? ???
  9. 実装(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 ??? ??? ??? ??? ???
  10. 実装(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 ??? ??? ??? ??? ???
  11. 実装(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
  12. 実装(2)使ったところだけ記録 • 0番目のクエリ: 初期状態 頂点番号 1 2 3 4 5

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

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

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

    4 5 クエリ番号 0 1 2 3 4 5 1 1 1 2 1 1 3 4 ??? ??? ??? ??? ??? 5 ??? ??? ??? ??? ???
  16. 実装(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 ??? ??? ??? ??? ???
  17. 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
  18. 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)回しか 呼ばれない
  19. 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)回しか 呼ばれない
  20. 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 ??? ??? ??? ??? ???
  21. 問題4 • N 頂点の無向グラフがある • Q 個のクエリをオンラインで処理せよ – u, v

    をつなぐ辺を追加 – i 番目のクエリを処理した時点における u を含む連結成分のサイズを出力
  22. 機能 • unite(u, v) – 頂点 u, v が含まれる連結成分を連結する •

    find(u, t) – t 番目のクエリを処理した時点における 頂点 u が含まれる連結成分の根を求める • size(u, t) – t 番目のクエリを処理した時点における 頂点 u が含まれる連結成分のサイズを求める
  23. 実装 • 表で持つ情報をちょっと変える – 今まで:親の番号だけ持たせていた 頂点番号 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
  24. 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
  25. 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)回しか 呼ばれない
  26. • 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)回しか 呼ばれない
  27. • 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)
  28. • 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)
  29. • 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)
  30. 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 ??? ??? ??? ??? ???
  31. 解ける問題 • AGC002 D: Stamp Rally • yukicoder No. 416:

    旅行会社 • CodeFesitival 2016 Elimination Tournament Round 1 A: グラフ • etc.