BZOJ 2152(点線のルール)

トピック:https://vjudge.net/contest/307753#problem/G

質問の意味:木はあなたがパスの総数を見つけることができますし、パスの数の3%

アイデア:点線の洪水の問題

#include <cstdioを> 
する#include <CStringの> 
する#include <cmath> 
の#include <アルゴリズム> 
の#include <iostreamの>  
する#include <ベクトル> 
の#include <キュー>
 の#define MAXN 100005
 の#define 0x3f3f3f3f MOD
 使用して 名前空間STD; 
typedefのロング ロング; LL 
DA LL、
ベクトル <ペア<-1,11,11- >> MP [MAXN]、XXは[MAXN]; // 十分図保存
; LL E [MAXN]
 BOOL VIS [MAXN]; // タグを用いた重力 
LLをMAXSIZE [MAXN]、DIS [MAXN]、フラグにD [MAXN]、[MAXN]; // 現在のノードのMAXSIZE最大サブツリー
SIZ LL [MAXN]、XDは[MAXN]; // 重力D距離の中心までDIS距離が現われ 
、LLのN-、M、K、RT、SUM、QE、QE2、ANS1、ANS2   // SIZ現在のノードのサブツリーE RTは、現在のフォーカスの数から明らか
ボイド {検索(XのLL、LL F)// 重心見つける 
    = SIZ [X]を1 ; 
    MAXSIZE [X] = 0 ;
     のためにINT I = 0 ;私はMPを[< X] .size(); Iは++ ){  <LL、LL> Q = MP [X] [I];
         IF(q.first == F || VIS [q.first])続行 ; // VIS配列タグ我々は重力を使用している
        (q.first、X)検索、
        SIZを[X] + = SIZ [q.first]と、
        MAXSIZE [X] = MAX(MAXSIZE [X]、SIZ [q.first]); 
    } 
    MAXSIZE [X] = MAX(MAXSIZE [X]、SUM-SIZ [X]); // ノードの総数マイナス現在のサブツリーの数=現在のノードは、父親のアイデア番号ツリーのルートである
    IF(MAXSIZE [X] < MAXSIZE [RT]){ 
        RT = X; 
    } 
} 
ボイドクエリ(LLのZ、LL SM){
     IF(Z> ANS1){ 
        ANS1 = Z; 
        ANS2 = SM; 
    } 
    そう IF(Z == ANS1){ 
        ANS2 + = SM; 
    } 
} 
ボイドget_dis(X LL、F LL、LL LEN){ 
    
    IF(LEN% 3。== 0)ANS1 ++ ; 
    ANS2 ++ ; 
    ANS1 + =フラグ[(3 -len%3 + 3)%3 ]。
    ANS2 + =フラグ[ 0 ] +フラグ[ 1 ] +フラグ[ 2 ]。
    E [lenの3 ] ++ ;
    以下のためにint型 i = 0 ; iは融点を<[X] .size(); iは++ ){  <-1,11,11-> Q = MP [X] [I];
        もし(q.first == F || VIS [q.first])続けます// DIS [q.first] =(DIS [X] + LEN)%3。
        get_dis(q.first、X、(LEN + q.second)%3 )。
    }     
} 
ボイド分割(LLのX){ 
    VIS [X] = 1 // のprintf( "RT =%LLD ANS1 =%LLD ANS2 =%LLD \ n"、X、ANS1、ANS2)。
    以下のためにint型 i = 0 ; iは融点を<[X] .size(); iは++ ){  <-1,11,11-> Q = MP [X] [I];
        もし(VIS [q.first])続けます// DIS [X] = q.second。
        get_dis(q.first、X、q.second%3 )。
        INT J = 0 ; J < 3; J ++ ){ 
            フラグ[J] + = E [J]。
            E [J] = 0 ; 
        } 
    } 
    のためにint型 i = 0 ; iは< 3 ; iは++ ){ 
        フラグ[I] = 0 ; 
    } 
    のためにint型 i = 0 ; iは融点を<[X] .size(); iは++ ){  <-1,11,11-> Q = MP [X] [I];
        もし(VIS [q.first])続けます// (ダ> 0)ブレークであれば、
        合計= SIZ [q.first]。
        RT = 0 ; 
        MAXSIZE [RT] = MOD。
        (q.first、X)を求めます。
        分割(RT)。
    } 
//     VIS [X] = 0; 
}
 ボイドのinit(){ 
    ANS1 = 0 ; ANS2 = 0 以下のためにint型私= 0 ; iが<= N; iが++ )MP [I] .clear();
    以下のためにint型 i = 0 ; iが<= N; iは++)VISを[I] = 0 ;
    以下のためにint型 i = 0 ; iは< 3 ; iは++)フラグ[I] = 0 ;
} 
int型のmain(){ 
    LLのT; 
    一方、(scanf関数(" %のLLD "!、&N)= {EOF)
        LL、B、C。
        その中に(); 
        以下のためにint型私= 1 ; I <= N- 1 ; iが++ ){ 
            scanf関数(" %LLD%LLD%LLD "、&​​、&B、&C)。
            MP [A] .push_back(make_pair(B、C))。
            MP [B] .push_back(make_pair(c)参照)。
        }      = N。// 当前节点数 
        RT = 0 ; 
        [MAXSIZE 0 ] = MOD。// 置初值 
        見つける( 10 ); 
        分割(RT)。
        ANS1 * = 2 ; 
        ANS2 * = 2 ; 
        ANS1 + = N。
        ANS2 + = N。
        W LL = __gcd(ANS1、ANS2)。
        // のprintf( "%LLD /%LLD \ n"は、ANS1、ANS2)。
        printf(" %LLD /%LLD \ n "、ANS1 / W、ANS2 / W)
    
    } 
}

 

おすすめ

転載: www.cnblogs.com/Lis-/p/11365917.html