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を返します。 }