CSP-Sアナログ試験51(b)の攻撃、ツリー解釈

質問表面:https://www.cnblogs.com/Juve/articles/11598286.html

攻撃:

ドミネーターツリー裸のタイトル?

支配的な木の外観はどのようなものです:

質問:私たちは、有向グラフ(有していてもよい環)を有し、始点Sとしてノードを設定します。今、私たちは尋ねる:すべてのパスがX-ポイント何{経由しなければならない点pに、始点Sから始まったp }。

換言すれば、X {削除Pを Xの内の任意の点まで} PI SはPに到達しないように、縁部にその縁。

この問題については、支配的なツリーの構築、それに

具体的な手順:

私たちは、ノードxは、新しいツリーの元にそのポイントLCAすべてに接続できるように、新しいツリーに達成するためにBFS

の浸透のポイントを減算しながら、この考え方によると、私たちは木にトポロジー、その親ノードの新しいアップデートを使用します

それが0度になると、LCAの方法との乗算は、新しい図面に追加します

ツリーの外に建てられ、その後、答えは新しいツリー内の各LCAのLCAにすべての問い合わせノードを依頼することです

書式#include <iostreamの> 
の#include <cstdioを> 
する#include <アルゴリズム> 
書式#include <CStringの> 
の#include <キュー> 
の#define再登録
std名前空間を使用しました。
const int型MAXN = 5E4 + 5。
const int型MAXM = 1E5 + 5。
N INT、M、Q、K、ANS = 0、デュ[MAXN]。
[MAXM << 1]、NXT [MAXM << 1]、プリ[MAXN]、CNT = 0にINT。
インラインボイド追加(再INT U、再INT V){ 
	++ CNTに[CNT] = V、NXT [CNT] =が予め[U]は、[U] = CNTを事前。
} 
INT F [MAXN] [22]、[MAXN]深いです。
INT LCA(int型のx、int型のY){ 
	IF(深い[X] <深い[Y])スワップ(X、Y)
	int型K =深い[X] -deep [Y]。
	以下のために(INT i = 0; iは<= 20; iは++)
		IF((1 << I)&K)
			X = F [X] [I]。
	もし(x == y)は戻りX。
	I> = 0;(I = 20 int型用
		IF(F [X] [I]!= F [Y] [i])と
			X = F [X] [i]は、YはF [Y] [I]を=。
	; F [X] [0]を返します 
} 
キュー<整数> Q。
ボイドBFS(INT ST){ 
	深い[ST]は= 1。
	q.push(ST); 
	一方、{(q.empty()!)
		INT X = q.front()。
		q.pop(); 
		以下のために(私は= [X]事前intです。私は、I = NXT [I]){ 
			[I]にINT Y =。
			IF(F [Y] [0]!)[Y] [0] = xとF。
			他F [Y] [0] LCA =([Y] F [0]、X)。
			F [Y] [0] = F [Y] [0]。
			深い[Y] =深い[F [Y] [0] + 1。
			--du [Y]。
			もし(DU [Y]!){ 
				q.push(Y)。
				用(int型J = 0であり、j <= 20; ++ J){ 
					IF(F [Y] [J-1])F [Y] [J] = F [F [Y] [J-1]] [ J-1]; 
				} 
			} 
		} 
	} 
} 
(){主符号付き
	のscanf( "%D%D%D"、&N、&M&Q)。
	{(; I <= M ++ iはi = 1、U、V INT)のため
		のscanf( "%D%dの"、&U、およびV)。
		追加(U、V); ++デュ[V]。
	} 
	BFS(1)。
	一方、(Q - ){ 
		scanf関数( "%のD"、&K); 
		scanf関数( "%のD"、&ANS)。
		(I = 1、VIをint型、I <K; ++ i)について{ 
			scanf関数( "%のD"、およびVI)。
			ANS = LCA(ANS、VI)。
		} 
		のprintf( "%d個の\ n"、深い[ANS])。
	} 
	0を返します。
}

木:

シンプルな木のDP?

確率はあなたをからかっています

セットサイズ[x]はxのサブツリーの大きさを示し、DP [x]は、時刻xの所望の数に初めて、次に表します。

$のDP [X] = DP [FA] + 2 *(N-サイズ[X])+ 1 $

書式#include <iostreamの> 
の#include <cstdioを> 
する#include <アルゴリズム> 
書式#include <CStringの> 
に#define int型、長い長い
名前空間stdを使用。
const int型MAXN = 1E5 + 5。
int型のn; 
[MAXN << 1]、NXT [MAXN << 1]、プリ[MAXN]、CNT = 0にINT。
ボイド追加(INT U、V INT){ 
	[CNT]へ++ CNTは、V、NXT [CNTを] = = [U]を事前に、[U] = CNTを事前。
} 
INT SIZ [MAXN]、DP [MAXN]。
ボイドDFS(int型のx、int型FA){ 
	SIZ [X] = 1。
	以下のために(私は= [X]事前intです。私は、I = NXT [I]){ 
		[I]にINT Y =。
		もし(Y == FA)続けます。
		DFS(Y、X)。
		SIZ [X] + = SIZ [Y]。
	} 
} 
ボイドDFS(int型のx、int型FA){ 
	(iは= [X]事前intです。私と、I = NXT [i])とするための{ 
		[I]にINT Y =。
		もし(Y == FA)続けます。
		DP [Y] = DP [X] + 2 *(N-SIZ [Y]) - 1。
		DFS(Y、X)。
	} 
} 
(){主符号付き
	のscanf( "%のLLD"、&N); 
	{(; iがN <++ iは、i = 1、U、V INT)のため
		のscanf( "%のLLDの%のLLD"、&U、およびV)。
		追加(u、v)は、追加(V、U); 
	} 
	DFS(1,0)。
	DP [1] = 1。
	DFS(1,0)。
	(I 1 = int型、iが<= N; I ++){ため
		のprintf( "%の0.3lfする\ n"、(二重)DP [I])。
	} 
	0を返します。
}

 

おすすめ

転載: www.cnblogs.com/Juve/p/11598352.html