フェイス質問
https://www.luogu.org/problem/AT3611
問題の解決策
点線は、各サブツリーラグランジュ点を見つけ、さらに点ラグランジュ点のハンドル側内のすべての木。
#include <cstdioを> する#include <iostreamの> する#include <アルゴリズム> の#include <CStringの> する#include <ベクトル> の#define N 200050 の#define INF 1000000007LL の#define RI intを登録 用いて 名前空間STDを、 INTのN、M、W [N]。 int型のSIZ [N]、VIS [N]; INT F [N]。 ベクター < INT > [N]に、LEN [N]。 構造体の縁{ int型Uを、V。 長い 長いリットル。 ブール 演算子 <(constのエッジ&RHS)CONST { 戻り L < rhs.l。 } } E [N * 50 ]。 INT findrt(INT X){ 場合(F [X] == x)をリターンX。 戻り [X] = F findrt(F [X])。 } ボイド FindRootで(int型のx、int型 FF、INT&RT、INT&RTS、int型のTOT){ int型 CURS = 0 。 SIZ [X] = 1 。 用(RI I = 0、L =に[X] .size(); iはLを<; iは++)場合(!の[X] [I] = FF && VIS [する[X] [I]]){ FindRootで([X]に[i]は、X、RT、RTS、TOT)。 SIZ [X] + = SIZ [i]は、[X] [します]。 もし(SIZ [する[X] [I]]> CURS)CURS = SIZ [する[X] [I]]。 } であれば(TOT-SIZ [X]> CURS)CURS = tot- SIZ [X]。 もし(CURS <RTS)のRTS =のCURS、RT =のX。 } ボイド findP(int型のx、int型 FF、INT&P、長い 長い&PD、長い 長いpredを){ 場合(predを+ W [X] <PD)PD = PRED + W [X]、P = X。 用(RI i = 0 ; iがLに<; I ++は、L =に[X] .size())もし(の[X] [I]!= FFの&&!VIS [[X] [I]に]){ findP([X] [i]は、X、P、PDに、predを + LEN [X] [I ]); } } ボイドリンク(int型のx、int型 FF、INT P、長い 長いPRED){ E [ + predを++ M] =(エッジ){X、P、[X]} W。 用(RI I = 0、L =に[X] .size(); iはLを<; iは++)場合(!の[X] [I] = FFの&& VIS [する[X] [I]]){ リンク([X] [i]は、X、Pに対して、predを + LEN [X] [I])。 } } ボイド tonji(int型のx、int型 FF、INT&TOT){ TOT ++ 。 用(RI i = 0 ; iはLを<I ++は、L = [X] .size())があれば(!の[X] [I] = FFの&& VIS [する[X] [I])tonji ([X]に[i]は、X、TOT)。 } ボイドは(解決INT X){ VIS [X] = 1 。 int型のp = - 1 ; 長い 長い PD = INF * INF。 findP(X、 - 1 、P、PD、0LL)。 リンク(X、 - 1 、P、PD)。 用(RI I = 0、L =に[X] .size(); iはLを<; iは++)場合(!VIS [する[X] [I]]){ int型 TOT = 0 ; ([X] [i]は、X、TOT)にtonji。 int型 RT = - 1、RTS = TOT; ([X] [i]は、X、RT、RTS、TOT)はFindRootで。 (RT)を解きます。 } } int型のmain(){ int型、B、Cと、 scanf関数(" %のD "、&N) 用(RI i = 1 ; I <= N; iが++)(scanf関数を" %のD "、&W [I])。 用(RI i = 1 ; iがn <; iは++ ){ scanf関数(" %D%D%D "、&、&B、& C)。 [A] .push_back(B)に、LEN [A] .push_back(C); [B] .push_backに(A)LEN [B] .push_back(C); }。 INT RT = - 1、RTS = N。 FindRootで(1、 - 1 、RT、RTS、N)。 (RT)を解きます。 ソート(E + 1、E + M + 1 )。 長い 長い ANS = 0 ; 以下のために(RI iは= 1 ; iが<= N; iは++)F [I] = I。 用(RI i = 1 ; I <= M; iは++ ){ int型、R1 = findrt(E [I] .U)、R2 = findrt(E [I] .V)。 もし(R1 == R2)続けます; 年 + = E [i]の.L。 F [R1] = R2。 } Coutの <<年齢<< てendl; リターン 0 ; }