CCFショックを受けNOIPは中断しますが、名前か何かのほとんどが変更されました。NOIP良いタイトルはまだやるを行うことができますが、この質問がやって本当に価値がある、私たちは明らかで、それが最小の最大値であり、問題は彼がすべての右側を通じて最短時間と意思決定の最大値であることであると言うのですか半分の答え。そのため、ツリーやチェーンのタイトルで、あなたはこの才能を考えることができますが、私は考えることはできません。暴力は、まず、M 1のものに等しい、30ヒット直接の最短経路側の2点マイナス最長の間の最短経路を得ます。O(形而上)、ダイクストラ最適化スタックのspfa複雑さは、O(nlogn)、手で30分間です。しかし、戦いは非常に肯定的な解決策は容易ではない、または問題の解決策を言う方法で確認するために、説明のほとんどは木の違いにこのようなものを言及したままです。我々は、第1の断面とLCAツリー、問い合わせ点間の距離を前処理毎に2年半+ツリー差分チェック、最小の最大値を確認するために確認を求め、と考えます。
これは、ツリーの違いの重要なステップである、それが推奨され、このブログを
我々は答えよりも大きなパスを見つけたら、何回記録後のパスの2つのエンドポイントを入れて、木の違いです。
茶[Q [i]は.fro] ++ ; 茶[Q [i]は.TO] ++ ? CHA [Q [i]は.lca] - = 2。
数行が、非常に便利なだけで、私たちはその後、超過回答の右側の最大値の間の差を計算します。違いのすべてのポイントの配列を更新した後、2つのツリーの間の唯一のパスなぜなら、あなたはあまりにも特定のポイントからしたい場合は、それが持っていた父親で開始する必要があります。そこで彼は、父親への差分値を蓄積しました。
ポイント共通点は、複数の側面がある場合、最終的に、判断があり、最大差分よりも右側が実行可能解である、ワームホールは、ドットの縁部に変更することができ、より大きな又は等しいです。
また、差分配列を空にするための答えの各半分は、すべて最初からやり直すことを覚えておいてください。O(nlogn)の最終的な複雑。
次のように完全なコードです
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 const int型 MAXN = 3E6 + 7 。 INT DEP [MAXN]、息子[MAXN]、サイズ[MAXN]、FA、[MAXN] W [MAXN]、DIS [MAXN]、ハッシュ[MAXN]。 INT TOP [MAXN]、ID [MAXN]、REV [MAXN]、時間; int型茶[MAXN]。 構造体ノード{ int型のNXT、ヴァル、であり; }エッジ[MAXN * 3 ]。 構造体ノード1 { int型前後に、LCA、ディス。 } Q [MAXN * 4 ]。 int型のヘッド[MAXN]、CNT; INTのN、M、X、Y、V、QX、QY。 INT 和、L、R。 ボイド追加(int型のx、int型の Y、INT V){ エッジ[ ++ CNT] .nxt = 頭部[X]。 エッジ[CNT] .TO = Y。 エッジ[CNT] .val = V。 ヘッド[X] = CNT。 } ボイド DFS1(int型のx、int型F){ FA [X] = F。 DEP [X] DEP [F] + = 1 。 サイズ[X] = 1 。 int型の maxson = - 1 ; 以下のために(int型 ; I I = I =ヘッド[X] {エッジ[I] .nxt) INT行く= エッジ[I] .TO。 もし(== FA [X]を行く)続けます。 DIS [移動] = DIS [X] + エッジを[I] .val。 DFS1(X、行きます)。 サイズ[X] + = サイズ[移動]。 もし(サイズ[移動]> maxson){ maxson = サイズ[進みます]。 息子は、[X] = 行きます。 } } } ボイド DFS2(int型のx、int型topf){ トップ[X] = topf。 もし(息子[X]!)を返します。 DFS2(息子[x]は、ポット)。 以下のために(int型 ; I I = I =ヘッド[X] {エッジ[I] .nxt) INT行く= エッジ[I] .TO。 場合(行く==息子[x]が行く|| == FA [X])続けます。 DFS2(行く、行きます)。 } } INT LCA(int型のx、int型のY){ 一方(上面[X] =!トップ[Y]){ 場合(DEP [TOP [X] < DEP [トップ[Y])スワップ(X、Y) X = FA [TOP [X]]。 } 戻り浅い[X] <浅い[Y]?X:Y。 } // --------------------------------ツリー断面シークLCAの上部 空隙 DFS3(INT X){ 用(int型 I =頭[X]を、I; I = エッジ[I]は.nxt){ int型ゴー= エッジ[I] .TO; IF(GO FA == [X])続けます。 DFS3(行きます)。 父[X] + = お父さん[進みます]。 } } ボイド dfs4(INT X){ ため(int型 I =ヘッド[X]; I; I = エッジ[I] .nxt){ int型行く= エッジ[I] .TO。 もし(== FA [X]を行く)続けます。 ハッシュ[戻る] = I; //は、エッジの数を記録し dfs4(行く)を、 } } ブールチェック(INT X){ int型 CNT = 0、年齢= 0 ; memset(チャ、0、はsizeof (CHA)) のための(int型私は= 1 ; I <= M、Iは++ ){ IF(Q [I] .diss> X){ // パスが存在する場合にない CHA [Qを[I]は.fro] ++; // ツリーに対応するレコードは+ +1当たり差分値重量の点である チャ[Q [I] .TO]は++ ; CHA [Q [i]は.lca] - = 2 。 CNT ++ ; ANS = MAX(ANS、Q [I] .diss- X); // 参照修飾最大値 } } IF(!CNT)のリターン をtrueに ; // 法的側面、この回答可能 DFS3(1); // 相違点の数をカウント するために(int型 I = 1を ;;私は= N-を<I ++)はIF(チャ[I ] == CNT &&エッジ[ハッシュ[I]ヴァル> = ANS)。戻る trueに; // 複数のエッジ点の共通点がある場合、最大差分値、実行可能解と等しいか大きいエッジの重みはである 戻り falseに; } INT {main()の scanf関数(" %d個の%のD "、&N、&M)。 以下のために(int型 i = 1 ; iがn <; iは++ ){ scanf関数(" %D%D%D "、およびX&Y、およびV)。 (X、Y、V)を追加し、(Y、X、V)を加えます。 } DFS1(1、0); DFS2(1、1); dfs4(1 )。 以下のために(int型 I = 1 ; I <= M; iは++ ){ scanf関数(" %dの%のD "、およびQX、&QY)。 Q [i]は.fro = QX。 Q [i]は.TO = QY。 Q [i]は.lca = LCA(Q [i]が.fro、Q [i]の.TO)。 Q [I] .diss = DIS [Q [I] .fro] + DIS [Q [I] .TO] - 2 * DIS [Q [I] .lca]; // 両者の前処理経路 和= MAX(和、Q [i]の .diss)。 } int型LJB; L = 0は、R = SUM; ながら(L <= R&LT){ // 最小最大見つける INT MID =(L + R&LT)/ 2 ; IF (チェック(MID)){ LJB = 半ば; R =半ば1 。 } 他リットル=ミッド+ 1 ; } printf(" %d個の\ n " 、LJB)。 リターン 0 ; }
良い質問。