ジム101810 M.貪欲海賊(LCA)

トピック:https://codeforc.es/gym/101810/problem/M

質問の意味:ここでは、あなたのツリーを与えるU-> Vを求めて、m個のクエリですが、最大数で、入力側との間に二点、肯定的な側面がある権利があり、抗抗エッジ権はその後、ありますQ U-> Vは、最大重量を受けることができるどのくらいです

アイデアは:我々は非Vサブツリーは、我々はすべて、紫外線のを完了し戻ってくるとVのサブツリーは、我々はまた、二つの側面を逆にすることができ、エッジを仕上げることができますどこに行くときに我々が見つかりますuのためのルートを始めます私たちは常にポイントが来てすべてを取得することはできません、最短の道は再び行くことができますので、この問題は、U-> V最長チェーンの最長チェーンの問題を見つけるために変換され、私たちは、m個のクエリを持っています我々は、実際にはでき最長鎖、2つのアレイは、現在の点からの距離のルートに正および負の重みによって記録され、根であり、そしてそれは事実DIS1のそれらの点から見ることができる描画[U] -dis1 [LCA (U、V)] + DIS2  [V] -dis2 [LCA(U、V)]

 

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
#define MST(SS、B)のmemset((SS)、(B)はsizeof(SS))
 のconst  int型 N = 1E5 + 5 int型、T、N、M、DIS [N]、DIS1 [N]、FA [N] [ 20 ]、FA1 [N] [ 20 ]、DEP [N]、DEP1 [N]、VS [N]、VS1 [ N]。
構造体ND {
     INT ; W 1、Wに対して、
}。
ベクター <ND> G [N]。
 
無効INITを(){
     ためint型 i = 1 ; iが<= N; iが++ )G [I] .clear(); 
    MST(DIS、0)、MST(FA、0)、MST(DEP、0)、MST(VS、0 ); 
    MST(DIS1、0)、MST(FA1、0)、MST(DEP 1、0)、MST(VS1、0 ); 
} 
 
ボイド DFS(INT X){ /// 得距離、深さ、父親にルートノードの各ノード 
    VS [X] = 1 ;
     のためのint型 I = 0 ; I ++は、IはG [X] .size()< ){ 
        ネオジムTP = G [X] [I]を;
         INT V = tp.to、tp.w = W、W1 = tp.w1;
         IF(VS [V])続行; 
        FA [V] [ 0 ] = X; 
        FA1 [V] [0 ] = Xは、
        DISは、[V] DIS [X] + = Wを、
        DIS1 [V] = DIS1 [X] + W1、
        DEP [V] = DEP [X] + 1。; 
        発1 [V] =発1 [X] + 。1 
        DFS(V); 
    } 
} 
 
ボイド BZ(){ /// 乗算前処理
    のためのINT J = 1。 ; J < 20である ; J ++)/// FA [I] [J]は、ノードIを表します2 ^ jの祖先
        のためにINT I = 1 ; I <= N; I ++ 
            FA [I] [J] = FA [FA [I]、[J- 1 ] [J-を1]、
            FA1 [I] [J] = FA1 [FA1 [I]、[J- 1 ]] [J- 1 ]; 
} 
 
int型 LCA(INT U、INT V){
     IF(DEP [U] <DEP [V] )スワップ(U、V); /// 注交換uおよびvは、DEP [U]とDEPを交換しない[V] 
    int型 D = DEP [U] - DEP [V];
     のためint型 I = 0、I < 20であり ; Iは++)/// 最初同じ深さに調整
        IF(D&(1)U = << I)FA [U] [I]は、
     IF(Uは== V)を返すUと、
     のためのINT I = 19 ; I> =0 ; i--){ /// 後方用なおであり、バイナリ分割、試行を降順
        IF(FA [U] [I] =!FA [V] [I]){ 
            U = FA [U ] [I]; 
            V = FA [V] [I]; 
        } 
    } 
    戻り FA [U] [ 0 ]; 
} 
 
int型のmain(){
     ながら(〜scanfの(" %のD "、&T)){
         一方(T - ){ 
            scanfの(" %のD "、およびN-)、
            INIT(); 
            ロング ロング ANS = 0 以下のためにint型 i = 1 ; iがn <Iは、++は){
                 int型、B、C、Dと、
                scanf関数(" %D%D%D%D "、&​​、&B、&C&D)。
                G [A] .push_back({B、C、D})。
                G [B] .push_back({、D、C})。
                ANS + = C + D。
            } 
            DEPは、[ 1 ] = 1、DISは、[ 1 ] = 0 
            DEP1 [ 1 ] = 1、DIS1 [ 1 ] = 0 ; 
            DFS(1)。
            BZ(); 
            scanf関数(" %のD "、&M)。
            以下のためにint型 I = 1 ; I <= M; iは++ ){
                 int型Uを、V。
                scanf関数(" %d個の%d個"、&​​U&V); 
                printf(" %LLDする\ n "、ans-(DIS1 [V] -dis1 [LCA(U、V)] + DIS [U] - DIS [LCA(U、V)]))。
            } 
        } 
    } 
    戻り 0 
}

 

おすすめ

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