[タイトル説明:
コンピュータサイエンスとエンジニアリングに根ざした木は、すべてのよく知らためのデータ構造の一種です。ここでは一例です。
8 - >(1,4,5); 1 - >(13,14); 4 - >(6,10); 5 - >(9); 6 - >(7,15); 10 - >(2 、11,16); 16 - >(3,12)。
この図において、各点はで表され、{1、2、...、16}数値的に標識されます。第8号は、ツリーのルートです。XのY個の点の数は、ルート・パスを指す場合、yはxの祖先です。例えば、4は、16、10の祖先です。実際には、8,4,10,16の祖先のすべて16。ノード自体が彼らの祖先であることを忘れないでください。別の例は、8,4,6,7 7の祖先です。
場合、両方のX、Y、Zの祖先の祖先はまた、X、Yと呼ばれ、そしてzが共通の祖先です。その共通の祖先8及び4は、16および7の両方です。
y、zは最近、最新の共通祖先のx y、zの中のすべての共通の祖先xの距離、y、zの場合は。すなわち、4近づくとして8、16 4及び7の代わりに8最新の共通の祖先です。
いくつかの例を挙げ:ノード2および3は、最新の共通の祖先ノード10であり、最も近い共通祖先ノードは、最も近い共通祖先ノード4ノード6及び13 8であり、ノード12は4です。YはZの祖先である場合、最後の例では、YとZの最新の共通の祖先はYです。
ツリーの2つの異なるノードの最新の共通の祖先を見つけるためのプログラムを書きます。
[入力説明:
最初の行、NおよびMは1からNまでのクエリノードとノード番号の数を表します。
次のN-1行、各二つの整数a、bは、Bは親ノードを示しています。
Mラインの後、それぞれの行は、彼らの最も最近の共通の祖先の問い合わせを示し、同じ2つの数字ではありません。
[出力]説明:
M行は、各列は、問い合わせの結果に対応する数を表します。
[サンプル入力]:
16 1
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
[]出力例:
4
[時間制限、およびデータの説明の範囲:
時間:1秒容量:256M
1 <= N、M <= 3000:データの40%を
1 <= N、M <= 2×10 ^ 5:データの100%まで
書式#include <アルゴリズム> 書式#include <iostreamの> の#include <CStringの> の#include <cstdioを> する#include <cmath> の#include <キュー> std名前空間を使用しました。 N INT、M、X、Y、CNT、リスト[500001]、S [500001]、D [500001]、[500001] F、HHH [500001]。 int型の息子[500001]、[500001] C。 構造体XO { 次にINT。 } [4 * 500001]。 ボイド追加(INT電子、INT R){ [++ CNT] .TO = R。 [CNT] .next =リスト[E]。 リスト[E] = CNT。 } ボイドDFS1(int型N、INT FA){ S [N] = 1。 D [N] = D [FA] +1。 F [N] = FA。 int型のTT; {(; I I = [I] .next I =リスト[n]がINT)のため TT = [I] .TO。 もし(TT!= FA){ DFS1(TT、N)。 S [N] + = S [TT]。 IF(!息子[X] || S [息子[N] <S [TT]){ 息子[n]はTTを=。 } } } } ボイドDFS2(int型N、INT FA){ C [N] = FA。 IF(息子[N]){ DFS2(息子[n]は、FA)。 } 他{ 返します。 } int型TT。 {(; I I = [I] .next I =リスト[n]がINT)のため TT = [I] .TO。 IF(!TT = F [N] && TT =息子[N]){ DFS2(TT、TT)。 } } } int型LCA(INT A、INT B){ ながら(C [A]!= C [B]){ IF(D [C [] <D [B] C]){ スワップ(B) } A = F [C []]。 } 戻りD [A] <D [B]:B;? } int型のmain(){ int型のFA。 scanf関数( "%d個の%のD"、&N、&M)。 (I 1 = int型、iが1、N <=; iが++){ため のscanf( "%D%D"、およびX&Y)。 (x、y)を加えます。 HHH [Y] = xと; 追加(Y、X)。 } ため(; iがn = <; I = 1 int型私は++){ IF(HHH [I] == 0){ FA = I。 ブレーク; } } DFS1(FA、0); DFS2(FA、FA)。 一方、(M - ){ scanf関数( "%d個の%のD"、およびX&Y)。 printf( "%d個の\ n"、LCA(X、Y))。 } 0を返します。 }