226最近の共通の祖先

[タイトル説明:

コンピュータサイエンスとエンジニアリングに根ざした木は、すべてのよく知らためのデータ構造の一種です。ここでは一例です。

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を返します。
}

  

おすすめ

転載: www.cnblogs.com/xiongchongwen/p/11230681.html