ソリューション:
まず、被験者は2点間のすべてのパスの最小のエッジ重みを求めるために私たちを必要とし、我々はしなければならない最小のエッジ権を最大化することで、我々はその最小の辺の重みが最大でなければならないことを、最大スパニングツリーのマップを得ることができます。最大スパニングツリーのパスの最小右側以外のパス上の最小エッジの重みがある場合、我々はその後、明らかに我々が壊れ最大スパニングツリーの最大の世代に並んで大きい方のも、別のものではないことができ、reductio広告absurdumを考慮することができますツリーは、(理解して描画を推奨)、および最大スパニングツリーの定義に矛盾します。
私たちは、我々はできる、2点間のパスは、これら2つのポイントに$ $ LCAそのパスに分けることができますので、すぐに2点のパスを見つける方法を検討し、$クラスカル$でツリーアルゴリズムをまたがる最大値を見つけることができます具体的には、2つの配列$ F [I、J]、最短経路が決定される$ LCA $結合乗算方法の問い合わせを評価する際の2点を選択 DP [iは、j]は$ $ I $ノードそれぞれノード番号と最小重量のその$ 2 ^ J $番目の祖先ノードへのパス。
次にあります。
$ DP [I、J] =分(DP [I、J-1]、DP [F [I、J-1、J-1])$
どちらも、オーバー$ $を得ることができるDFSです。
詳細は、注意が必要です。この数字は通信できない場合があり、最大スパニングツリーが$をDFS時にすべてやり直す$ DFSの注意を求めています。
最後に、コードを添付:
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 CONST INT N = 10005、M = 50005、INF =(1 << 30 )。 int型版C [N]、[M]、NXT [M]、エッジ[M]、ヘッド[N]、D [N]、F [N] [ 20 ]、DP [N] [ 20 ]。 整数N、M、CNT、TOT、T、Q。 BOOL VIS [N]。 構造体の点{ INT U、V、lenの; ブール 演算子 <(CONSTポイント&)のconst { 戻り a.len < LEN;} } EDGE1 [M]。 int型リード(){ int型X = 0 。 チャー CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 ')CH = GETCHAR()。 一方、(CH> = ' 0 ' && CH <= ' 9 '){X =(x << 3)+(X << 1)+ CH- ' 0 ' ; CH = GETCHAR();} 戻りX。 } INT getfather(INT X){ リターン X == C [X]?X:C [X] = getfather(C [X])。 int型のx、int型 Y、INT Z){版[++ TOT = Y、エッジ[TOT = Z、NXT [TOT =頭部[X]、ヘッド[X] = TOT;} ボイド DFS(int型X) { VIS [X] = 1 。 以下のために(INT iがヘッド[x]は、yは=; I;私は= NXT [I]){ 場合(VIS [Y =版[I])を続けます。 D [Y] = D [X] + 1、F [Y] [ 0 ] = X、DP [Y] [ 0 ] = エッジ[I]。 用(INT J = 1 ; J <= T; ++ j)は{ F [Y] [J] = F [F [Y] [J- 1] [J- 1 ]。 DP [Y] [J] =分(DP [Y] [J- 1 ]、DP [F [Y] [J- 1 ]] [J- 1 ])。 } DFS(Y)。 } } int型 LCA(int型のx、int型のY){ int型 ANS = INF。 もし(D [X]> D [Y])スワップ(X、Y) 用(INT I = T、I> = 0 ; - I){ 場合(D [F [Y] [I]]> = D [X]){ ANS = 分(ANS、DP [Y] [I] ); Y = F [Y] [I]。 } } もし(x == y)は戻りANS。 用(INT ; I> = I T = 0 ; i-- ){ 場合(!F [x]は[I] = F [Y] [I]){ ANS = 分(ANS、分(DP [X] [ i]は、DP [Y] [I]))。 X = F [X] [i]は、Yは= [Y] F [i]は、 } } 戻り ANS =分(ANS、分(DP [X] [ 0 ]、DP [Y] [ 0 ])); } int型{)(メイン N =(読み取り)、M = read()は、 T =(INT)(ログ(N)/ログ(2))+ 2。 以下のために(INT iが= 1 ; I <= M; ++ I)EDGE1 [++ CNT] .U =(読み取り)、EDGE1 [CNT] .V =(読み取り)、EDGE1を[CNT] .LEN = (読み取り) ; 以下のために(INT iが= 1 ; I <= N; ++ I)C [I] = I。 ソート(EDGE1 + 1、EDGE1 + 1 + CNT)。 用(INTは iは= 1 ++; I <= CNT {//クラスカル求最大生成树I) INT X = EDGE1 [I] .U、Y = EDGE1 [I] .V、Z = EDGE1 [I]。 LEN; INT FAA = getfather(X)、FAB = getfather(Y)。 もし(FAA == FAB)続けます。 C [FAB] =FAA; (x、y、z)を追加し、(X、Y、Z)を加えます。 } ため(INT iは= 1 ; I <= N; ++ I)の場合(!VIS [I]){D [I] = 1 、DFS(I);} Q = read()は、 用(INT iは= 1 ; I <= Q ++、X、Y {I) X =(リード)、Yは= (読み取り) INT FAA = getfather(X)、FAB = getfather(Y)。 もし(FAA = FAB!){のprintf(" -1 \ n "); 引き続き;} //不在一个连通块内 のprintf(" %D \ n "、LCA(X、Y))。 } 戻り 0 。 }