質問表面: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を返します。 }