【AtCoder3611】ツリーMST

フェイス質問

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、INTTOT){ 
  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 ; 
}

 

おすすめ

転載: www.cnblogs.com/shxnb666/p/11275664.html