アドバンス

ZZます。https://blog.csdn.net/rzo_kqp_orz/article/details/52280525
小さなZはETGを開始しました。ETGツリーマップは、二つの隣接する部屋、先頭からの距離であり、システムがランダムので、このことは、エッジを切断します
マップが通信しているが、2つのブロックに分割されます。もちろん、狡猾なシステムは、各ユニコムの右側にある4つの胸二十から二最遠点で配布されます。最初は、小さなZをされる
の胸(システムは良心のビットはまださ)がある部屋で生まれ、その後、小さなZ「ブームブームブーム」の別の胸があり、すべての道に行った
地面を(明らかに小さなZは、最短経路を取ります)第二胸の位置に到達した後、システムは別のブロックへの通信で非常に良心的な彼の胸には、なります
し、別の小さなZ「はポンドをタップ」、最後の胸を取得します。それから彼はオフに渡します。Zは小さな隙間がはい、とても小さいZがしたかったされ、明らかにされ
、彼は距離まで歩いてどのくらい知っています。

入力
最初の行の入力は、整数N、部屋の数を含んでいます。
次いで、N-1の3つの正の整数の行は、x、yは、Dは、部屋Dの部屋のxとyの距離を表します。
N <= 100,000ジ<= 100,000

出力の
出力のラインは整数を含み、Zは最も逃げるの小さな距離を表します。

サンプル入力
6
1 3 4
2 3 1
2 3 5
2 6 2
3 4 5

サンプル出力
14

データ制約

データ満たすN <= 1000の50%。
データを満たすの100%に

意図した対象が
ツリーが与えられ、その後、端から2つのツリーと直径と生成をカットを選択することができます。そして、最大値を求めます。
[50%] N <= 1000
次に列挙破断縁、および暴力の直径を見つけます。
方法1 [100%] N <= 10 ^ 5
ツリーメンテナンスと直径セグメントツリー。
元のツリー単離さサブツリーに相当するエッジを、オフ範囲複合列挙は、我々は、木直径サブツリーにセグメントツリーを検索し、次に直径の残りの部分に別の外観を得ることができます。
倍加時間必要なLCAは、O(nは2 ^ログ)である場合には、スタックになります。
RMQ LCA時間O(Nログ)によって必要に応じて
HTTP://直径セグメントツリー保守ツリー//blog.csdn.net/rzo_kqp_orz/article/details/52280811
[100%]方法2
質問これは例示であり、裸木のDP!
元の問題の解決策は、「裸木DP、D1 [I](最長鎖)、D2 [i]は(CI長鎖)、FA [I](I父親最長経路と上記)が可能な記録。 Oの時間計算量(n)を。 "
アイデアは非常に単純ですが、メンテナンスの戦いはもっと議論します。

#include <cmath> 
の#include <cstdioを> 
する#include <アルゴリズム> 
のための#define FO(I、B)(INT iが=; I <= B; I ++)
の#define FD(I、B)のための(INT iは=; I> = B; i--)
名前空間stdを使用。

長い長いLLのtypedef。

CONST INT MAXN =(1E5)+5、MX = 18。

構造体TR { 
    int型のX、Y。
    LLのlen; 

    TR(INT X = 0、Y = INT 0、LL LEN = 0){X = X、YはYにおいてlen = LENを=;} 
}。

int型のn; 

int型のTOTは、[2 * MAXN]、次の[2 * MAXN]、F1 [MAXN]行きます。
LLヴァル[2 * MAXN]。
ボイドイン(int型のx、int型のY、LLのZ)
{ 
    Y = [++ TOT]行きます。
    ヴァル[TOT = Z。
    次【TOT] = F1 [X]。
    F1 [X] = TOT。
} 
 
INT FA [2 * MAXN] [MX + 5]、深い[MAXN]、AP [2 * MAXN]、FIR [2 * MAXN]、ログ[2 * MAXN]、ER [MX + 5]。
ボイドrmq_pre()
{
    (I 1、AP [0])FA [i]が[0] = AP [i]は、ログ[I] =ログ(I)/ログ(2)FO。
    (I、0、MX)ER FO [I] = 1 << I。
    (J、1、MX)FO 
        FO(I、1、AP [0])
        { 
            FA [I] [J] = FA [I] [J-1]。
            IF(I + ER [J-1] <= AP [0] &&深い[FA [I + ER [J-1] [J-1] <深い[FA [I] [J])
                FA [ I] [J] = FA [I + ER [J-1] [J-1]。
        } 
} 
int型LCA(int型のx、int型のY)
{ 
    X = FIR [X]、Y = FIR [Y]。
    (X> Y)スワップ(X、Y)であれば、
    INT T =ログイン[Y-X + 1]。
    リターン(深い[FA [X] [T] <深い[FA [Y-ER [T] +1] [T])FA [X] [T]:FA [Y-ER [T] +1 ] [T]。
} 

INT ST [MAXN]、EN [MAXN]、和、TBH [MAXN]。
LLのDIS [MAXN]。
無効dfs_pre(int型のk、int型最後、LL秒)
{ 
    深い[K] =深い[最終] +1。
    DIS [K] = S。 
    AP [++ AP [0] = K、FIR [K] = AP [0]。
    TBH [++和] = K、ST [K] =和。
    以下のための(int型のp = F1 [K]; P; P =次の[P])であれば(行く[P] =最後!)
    { 
        dfs_pre(行く[P]、K、S +ヴァル[P]); 
        AP [++ AP [0] = K。
    } 
    EN [K] =和。
} 

TR TR [4 * MAXN]。
LL DIS(int型のx、int型Y){戻りDIS [X] + DIS [Y] -dis [LCA(X、Y)] * 2;} 
TRマージ(TR、TR b)は
{ 
    TR再=(。 LEN> b.len):B;?
    IF(DIS(AX、BX)> re.len)再= TR(AX、BX、DIS(AX、BX))。
    (DIS(AX、による)> re.len)再= TR(AX、DIS、によって(AX)によって)場合、
    IF(DIS(AY、BX)> re.len)再= TR(AY、BX、DIS(AY、BX))。
    IF(DIS(AY、による)> re.len)再= TR(AY、DIS(AYによって、)によります)。
    再を返します。
}
ボイドtr_js(int型K、INT L、int型R)
{ 
    IF(L == R)
    { 
        TR [K] .X = T R [K] .Y = TBH [L]。
        TR [K] .LEN = 0。
        リターン; 
    } 
    INT T = K << 1、T1 =(L + R)>> 1。
    tr_js(T、L、T1)、tr_js(T + 1、T 1 + 1、R)。
    TR [K] =マージ(TR [T]、TR [T + 1])。
} 
TR tr_cx(INT K、INT L、INT R、int型のx、int型Y)
{ 
    IF(L == X && R == y)は戻りTR [K]。
    INT、T = K << 1、T1 =(L + R)>> 1。
    もし(Y <= T1)戻りtr_cx(T、L、T 1、X、Y)
        他の場合(X> T1)戻りtr_cx(T + 1、T 1 + 1、R、X、Y)。
            他戻りマージ(tr_cx(T、L、T 1、X、T1)、tr_cx(T + 1、T 1 + 1、R、T1 + 1、Y))。
} 

LL ANS。
無効DFS(int型K、INT最後) 
{
    (; P; int型のp = F1 [k]は、P =次の[P])のために(![P]を行く=最後)の場合
    { 
        int型セント= stが[] P [進む]エン=アン、[[P]を行きます] ; 
        (ST == 1)であれば
        { 
            ANS = MAX(ANS、tr_cx(1,1、N、ST、JA).LEN + tr_cx(1,1、N、エン+ 1、n)は.LEN)。
        }そうであれば(JA == N)
        { 
            ANS = MAX(ANS、tr_cx(1,1、nは、1、ST-1).LEN + tr_cx(1,1、N、ST、JA).LEN)。
        }他
        { 
            TR T =マージ(tr_cx(1,1、nは、1、ST-1)、tr_cx(1,1、N、エン+ 1、N))。
            ANS = MAX(ANS、t.len + tr_cx(1,1、N、ST、JA).LEN)。
        } 

        DFS(GO [P]、K)。
    } 
} 

int型のmain()
{ 
    scanf関数( "%のD"、&N); 
    (I、1、N-1)FO 
    {
        INT X、Y。LLのD;  
        IF(V> V1)U3 = U2、V3 = V2、U2 = U1、V2 = V1、U1 = U、
        scanf関数( "%D%D%LLD"、およびX&Y、&D)。
        イン(X、Y、D)、イン(Y、X、D)。
    } 

    dfs_pre(1,0,0)。
    rmq_pre(); 
    tr_js(1,1、N)。

    DFS(1,0)。

    printf( "%のLLD \ n"は、ANS)。
} 

の#include <cstdioを> 
する#include <CStringの> 
する#include <アルゴリズム> 
の#define I64長い長い
名前空間stdを使用。

CONST INT N = 1E5 + 10。
INT、N、R [N]、TOT。
I64 ANS; 

構造体の縁{INT、T、L、N;} E [N * 2]。

構造体のリンク{ 
    I64 V1、V2、V3。
    int型U1、U2、U3; 
    ボイドイン(INT U、V I64){ 
        他(V> V2)U3 = U2、V3 = V2、U2 = U、V2 = Vであれば、
        それ以外の場合(V>
    } 
} L [N]。

I64 MAX(I64 X、I64 Y){リターンX> Y?X:Y;} 

ボイド追加(int型のx、int型Y、Z INT){ 
    E [++ TOT] .T = Y。E [TOT] .L = Z。E [TOT] .N = R [X]。R [X] = TOT。
} 

ボイドDFS(INT U、INT FA){ 
    L [U] .u1 = L [U] .u2 = L [U] .v1 = L [U] .V2 = 0。
    (INT I = R [U]; iは、iはE [I] .N =)用{ 
        int型、V = Eを[I] .T。
        (V == FA)は継続であれば、
        DFS(V、U); 
        I64、T = L [V] .v1 + E [I] .L。
        L [U]の.ins(V、T)。
    } 
} 

ボイドAWN(INT U、INT FA、I64 LL、I64 MX){ 
    ため(INT I = R [U]; I; Iは、E [I] .N =){ 
        int型、V = E [I] .T。
        (V == FA)は継続であれば、
        I64、T = 0、MM = 0。
        IF(L [U] .u1 == V)T = L [U] .V2。
        他T = L [U] .v1。
        IF(L [U] .u1 == V)MM = L [U] .V2 + L [U] .v3。
        他の場合(L [U] .u2 == V)MM = L [U] .v1 + L [U] .v3。
        他のMM = L [U] .v1 + L [U] .V2。
        ANS = MAX(ANS、L [V] .v1 + L [V] .V2 + MAX(MM、MAX(MX、LL + T)))。
        AWN(V、U、MAX(LL、T)+ E [I] .L、MAX(MM、MAX(MX、LL + T)))。
    } 
} 

int型のmain(){ 
    scanf関数( "%のD"、&N); 
    以下のために(INT I 1 =; N I <; I ++){ 
        int型は、U、V、W。
        scanf関数( "%D%D%D"、&U&V、およびW)
        (U、V、W)を加えます。(V、U、W)を加えます。
    } 
    DFS(1、0);
    AWN(1、0、0、0); 
    printf( "%のLLD"、ANS)。
    0を返します。
}

  

おすすめ

転載: www.cnblogs.com/cutemush/p/11831036.html