差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
次のリビジョン両方とも次のリビジョン
programming_algorithm:graph_theory:lowest_common_ancestor [2019/11/28] – [EulerTour + RMQ] ikatakosprogramming_algorithm:graph_theory:lowest_common_ancestor [2019/11/29] – [EulerTour + RMQ] ikatakos
行 33: 行 33:
 ==== EulerTour + RMQ ==== ==== EulerTour + RMQ ====
  
-オイラーツアーで通りかかった順番に頂点と深さを記録していく。また、その過程で以下の情報も記録していく。+===オイラーツアー=== 
 + 
 +オイラーツアーは、深さ優先探索で通りかかった順番に頂点を記述する方法。$N-1$ 辺を行き帰りで2回ずつとおるので、出発点と合わせて長さ $2N-1$ の配列になる。 
 + 
 +       0 
 +      /  \    
 +     1  2    0, 1, 3, 5, 3, 1, 4, 1, 0, 2, 0 
 +    / \ 
 +   3 4 
 +   | 
 +   5 
 + 
 +この変換により、木の祖先・子孫関係をわかりやすい形(1次元配列)で持つことができるため、 
 +1次元配列で扱える様々なデータ構造を利用できる。BIT、セグメント木、など。 
 + 
 +===オイラーツアーを用いたLCA=== 
 + 
 +LCAを求めるには、オイラーツアーで通りかかった順番に頂点と深さを記録していく。また、その過程で各頂点が最初に現れた位置も記録していく。
  
   * ''eular_tour[i] = (d, v)''   * ''eular_tour[i] = (d, v)''
-    * $i = 0 ~ 2(N-1)$ について、$i$ 番目に通りかかる頂点の(深さ, 頂点番号) +    * $i$ 番目に通りかかる頂点の(深さ, 頂点番号)
-  * ''depth[v] = d'' +
-    * 頂点 $v$ の深さ+
   * ''first_appear[v] = i''   * ''first_appear[v] = i''
     * 頂点 $v$ がeular_tour上で初めて現れるindex     * 頂点 $v$ がeular_tour上で初めて現れるindex
行 46: 行 61:
      1  2                v: 0, 1, 3, 5, 3, 1, 4, 1, 0, 2, 0]      1  2                v: 0, 1, 3, 5, 3, 1, 4, 1, 0, 2, 0]
     / \     / \
-   3 4     depth = [0, 1, 1, 2, 2, 3] +   3 4     first_appear = [0, 1, 9, 2, 6, 3] 
-   |        first_appear = [0, 1, 9, 2, 6, 3]+   |
    5    5
  
 こうすると、頂点 $a$ と $b$ のLCAは、以下で求められる。 こうすると、頂点 $a$ と $b$ のLCAは、以下で求められる。
  
-  * ''ai = first_appear[a], bi = first_appear[b]''を取得する(それぞれの初登場index)+  * それぞれが ''eular_tour'' 上ではじめて現れるindex $a_i,b_i$ を取得する
     * $a_i \lt b_i$ と仮定する     * $a_i \lt b_i$ と仮定する
-  * ''euler_tour''上で、区間 $[a_i, b_i]$ 内、depthが最小となる頂点がただ1つ存在する +  * ''euler_tour''上で、区間 $[a_i, b_i]$ 内から、depthが最小となる頂点を取得する 
-  * そいつがLCAである+  * そいつがLCAである(このような頂点はただ1つ存在する)
  
-  頂点5と4 → ai = 3, bi = 6+  頂点(a, b) = (5, 4) のLCAを求める 
 +    → ai = 3, bi = 6
   eular_tour[3:6] = [(3, 5), (2, 3), (1, 1), (2, 4)]   eular_tour[3:6] = [(3, 5), (2, 3), (1, 1), (2, 4)]
   この中で最小は (1, 1) なので、深さ1の頂点1がLCA   この中で最小は (1, 1) なので、深さ1の頂点1がLCA
行 63: 行 79:
 もし、LCAの頂点番号は不要で、深さだけが求められればいい場合、''eular_tour'' で管理するのは $d$ のみでよい。 もし、LCAの頂点番号は不要で、深さだけが求められればいい場合、''eular_tour'' で管理するのは $d$ のみでよい。
  
 +===区間最小値===
  
 ここで、区間の最小値を求めるクエリRmQが発生する。以下のアルゴリズムなどで解ける。 ここで、区間の最小値を求めるクエリRmQが発生する。以下のアルゴリズムなどで解ける。
programming_algorithm/graph_theory/lowest_common_ancestor.txt · 最終更新: 2020/05/10 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0