880 likes | 1.07k Views
最下位共通先祖問題と MF 木. ** ここで理解すべき内容 ** 抽象データ型 Merge-Find 集合 ( Union-Find 集合) データ構造 Merge-Find 木 ( Merge-Find tree ) 計算量評価方法 均し計算量 ( amortized complexity ). 例として考える問題. オフライン 最下位共通先祖 問題. オフライン最下位共通先祖問題. Off-line Lowest Common Ancestors Problem 入力: 根付き木 T = (V,E)
E N D
最下位共通先祖問題と MF 木 ** ここで理解すべき内容 ** • 抽象データ型 • Merge-Find 集合 (Union-Find 集合) • データ構造 • Merge-Find 木 (Merge-Find tree) • 計算量評価方法 • 均し計算量 (amortized complexity)
例として考える問題 オフライン 最下位共通先祖 問題
オフライン最下位共通先祖問題 • Off-line Lowest Common Ancestors Problem • 入力: • 根付き木 T = (V,E) • 点対の集合 P = { p=(v,w) | v, w は T の点 } • 出力: • 各点対 p=(v,w)∈P に対する (木 T 上での)最下位共通先祖 anc(p)
最下位共通先祖 • 木 T 上の質問点対 p=(v,w) に対する 最下位共通先祖 anc(p) = a 木 T の点 a で,以下の性質を持つもの • v と w の共通の先祖であり, • a の真の子孫には v と w の共通の先祖が無い
質問点対の集合 P P = { (c,h), (e,f), (f,g), (g,h) } オフライン最下位共通先祖問題 木 T b d c e • 最下位共通先祖 • anc( (c,h) ) = b • anc( (e,f) ) = e • anc( (f,g) ) = b • anc( (g,h) ) = d f a h g
オフライン(off-line)問題 • オフライン(off-line)問題 • 全ての質問を予め知った上で 各質問に対する答えを求めるもの • オンライン(on-line)問題 • 全質問を予め知ることができず, 質問毎に答えを出すもの
オフライン最下位共通先祖問題に対するアルゴリズムオフライン最下位共通先祖問題に対するアルゴリズム
アルゴリズム • 木 T を深さ優先探索(DFS)して求める. • void DFS( v, T ) { • 行きがけの処理 ; • c := lm_child(v) ; /* c を v の長男に */ • while (子 c が存在する ) { • DFS( c, T ) ; • 子 c の情報を利用する処理 ; • c := r_sibling( c ) ;/* c を次弟に */ • } • 帰りがけの処理; • } /* end DFS */ • 帰りがけに,最下位共通先祖が求められる ? r v c' c
点 v からの帰りがけ時の検査 b • (v,w)∈P なる質問点対が存在し w は既に探索済みか? • もし,そうならば, • w の先祖で探索中の点の内, 最下位にある点 a は, v と w の最下位共通先祖 anc((v,w) ) d a e w v
必要な操作 b • 1. 点 v を含む質問点対 (v,w) ∈P が存在するか否かの検査 • 2. もう一方の点 w は既に探索済みか否かの検査 • 3. w の探索中の先祖で,最下位の点の探索 • これらを効率良く実行したい d a e w v
必要な操作 1 • 点 v を含む質問点対 (v,w)∈P が存在するか否かの検査に対しては, • 木 T の各点 v に対して, v を含む質問点対 p=(v,w) ∈ P の集合 P(v) = { p | p=(v,w)∈ P } を覚えておく w w' v
必要な操作 2 b • 点 v を含む質問点対 (v,w)∈P のもう一方の点 w が, 既に探索済みか否かの検査は • 点に • 未探索 • 探索中 • 探索済み の印を付けておけば良い d a e w v
必要な操作 3 b • 点 w の探索中の先祖で, 最下位のもの a を求めるには, • “探索中” の各点 a に対して, 集合 U(a) = { a } { w, ・・・} • w は a の子孫で探策済み, • w の先祖で a より下に探索中の点は無い を覚える • w ∈U(a) と現在探索中の点 v との 最下位共通先祖は a = anc( (v,w) ) • U(a) の初期値は, U(a) = { a } とする d a e w v
アルゴリズムの例 集合 U(・) に対する操作
木 T と集合 U(・) および P(・) A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
探索中 木 T の深さ優先探索 A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
木 T の深さ優先探索 A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T 探索中 b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
木 T の深さ優先探索 A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
木 T の深さ優先探索 A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
探索済 点 g の探索終了: P(g) の検査 A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g f, h は未探索 ⇒ 何もしない
A = U(a) = { a, g } 点 g から戻る: A と G の併合 A = U(a) = { a } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 a に戻った A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 a の探索終了: P(a) は空 A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
D = U(d) = { a, d, g } 点 a から戻る : A と D を併合 A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { d } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 d に戻った A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 h を深さ優先探索 A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 h の探索終了: P(h) の検査 A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g g は探索済み ⇒ anc((g,h)) は?
点 g を含む集合 U(・) の探索 A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g g ∈ U(d) ⇒anc((g,h)) = d
D = U(d) = { a, d, g, h } 点 h から戻る : H と D を併合 A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 d に戻った A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 d から戻る A = U(a) = { a, g } B = U(b) = { b } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g P(d) は空 ⇒ B と D を併合
点 b に戻った A = U(a) = { a, g } B = U(b) = { a, b, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 c を深さ優先探索 A = U(a) = { a, g } B = U(b) = { a, b, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 c の探索終了: P(c) の検査 A = U(a) = { a, g } B = U(b) = { a, b, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T h を含む U(・) は? ⇒anc((c,h)) = b b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g h は探索済み ⇒ anc((c,h)) は?
点 c から戻る : C と B を併合 A = U(a) = { a, g } B = U(b) = { a, b, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 b に戻った A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 e, f へ深さ優先探索 A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 f の探索終了 : P(f) の検査 A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T g を含む U(・) は? ⇒anc((f,g)) = b b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g g は探索済み ⇒ anc((f,g)) は?
点 f から戻る : F と E の併合 A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 e に戻った A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e, f } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
点 e の探索終了 A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e, f } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T f を含む U(・) は? ⇒anc((e,f)) = e b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g f は探索済み ⇒ anc((e,f)) は?
点 e から戻る : E と B の併合 A = U(a) = { a, g } B = U(b) = { a, b, c, d, g, h } C = U(c) = { c } D = U(d) = { a, d, g, h } E = U(e) = { e, f } F = U(f) = { f } G = U(g) = { g } H = U(h) = { h } 木 T b d c e f a h P(c) = { (c,h) } P(e) = { (e,f) } P(f) = { (e,f), (f,g) } P(g) = { (f,g), (g,h) } P(h) = { (c,h), (g,h) } g
根 b に戻り 木 T B = U(b) = { a, b, c, d, e, f, g, h } b b d c e f a h 全探索終了 g
アルゴリズムの記述と計算量 深さ優先探索の再帰的記述
アルゴリズムの概要 • void DFS( v, T ) /* 再帰的関数 */ • 木 T の点 v を根とする部分木の深さ優先探索をする関数 • 入力: v : NODE(値呼び) • T : 木 • P(v) : v を含む質問点対の集合 • 出力: anc(p) : 各質問点対 p に対する 最下位共通先祖 • NODE c /* 局所変数 */ • 各点 v に対して,未探索の印しを付けておき, • 集合 U(v) の初期化U(v) = { v } を行って, • 関数 DFS( 木 T の根,T ) を呼ぶ.
アルゴリズムの概要 • voidDFS( v, T ){ • v に探索中の印を付ける ; • c := lm_child(v) ; • while(子 c が存在する ) { • DFS( c, T ) ; • U(c) を U(v) に併合する ; • c := r_sibling( c ) ;} • for ( 各 p=(v,w)∈P(v) ) { • if (点 w は探索済み ) { • 点 w を含む U(a) を求める ; }} • v に探索済みの印を付ける ; • } /* end DFS */ 実は不要 Merge( ) Find( )
集合 U(・) に対する操作 • 指定された点 w を含む集合 U(a) を見出す Find( w ) 計算量を O(TF)と書く • 点 a は点 v と w の最下位共通先祖 • 集合 U(v) と U(c) を併合し,U(v) とする Merge( U(c), U(v), U(v) ) 計算量を O(TM)と書く
アルゴリズムの計算量 • どの点も高々 1 回しか訪問しない • 点 v に関する下記の操作は 1 回しか実行しない • 各点における操作 • Merge の操作 • 質問点対があれば,Find の操作 • 子を順に探索するための操作 • 全 Merge 回数: n-1 回 (n : 点の個数) • 全 Find 回数: m 回 (m : 質問点対の個数) • 全計算量 • O( 全 Merge の計算量 + 全 Find の計算量 + その他 ) • = O( (n-1)・TM + m・TF + n )
Merge-Find 集合とMerge-Find 木 Merge, Find に対する 効率的なデータ構造
Merge-Find 集合 (MF set) • 以下の操作を持った抽象データ型 • Merge( A, B, C ) • 互いに素な集合 A および B に対して, C := A∪B とする手続き. • A∩B=φなる集合 A, B に対する Union( A, B, C ) と同じ. • Find( x ) • 要素 x を含む集合を返す関数. • Initialize( A, a ) • 要素 a だけから成る集合 A を作る手続き