タイトル説明:https://www.luogu.org/problem/P2387
分析:2ポイントのUVは、それらの間に小さな値をエッジ、b値も小さい:、その後、明らかに貪欲ではないと思うの最大値は、対象の最低要件である第一に考え二つの点が、2つの変数があります間違いなく良い方。だから値による最初の側面、そしてb値により最小スパニングツリーを維持します。それは手に負えない最小スパニングツリーに出現した場合に新たに挿入された側のために、我々は、元のその端を切断、それがある場合に側端で最大のリングは、これよりも大きいクエリ。最小スパニングツリーにそれを維持するために、どのように何I風雲?明らかにLCT。しかし、我々はその境界を維持したい、それを行う方法?ルーチンはマルチポイントを構築することです、そして右側、最初と最後に割り当てられたポイントの値は、それぞれ、この辺に接続することができます。
詳細:1.いいえ詳細は、ハングのように書いていません。
コードを接続します。
#include <cstdioを> する#include <iostreamの> する#include <アルゴリズム> 使用して 名前空間STD; // グラフが与えられると、各エッジは、出発点への経路を見つけるために、2 AB&重みを有する // ように、このパスを最大値と最大値と最小値Bは上 CONST INT MAXN = 50005、MAXM = 200005 ; INT N-、M、 構造体のエッジ{ INT U、V、B; }エッジ[MAXM]; int型FA [MAXMを]; 構造体ノード{ int型 MAX、ヴァル、息子[ 2 ;〕、FA BOOLのflag_reverse; }ノード[MAXMを << 1 ]; INTANS = 0x3f3f3f 。 INT STK [MAXM << 1 ]。 インラインint型リード(){ int型 RET = 0、F = 1。チャー C = GETCHAR()。 一方、(C < ' 0 ' || C> ' 9 '){ もし、(C == ' - ')= -f F; C = GETCHAR();} 一方、(C> = ' 0 ' && C <= ' 9 '){RET = RET * 10 + C- ' 0 '; C = GETCHAR()} 戻りのRET *のF。 } ボイド readIn(INT I){ エッジ[I] .U読み取り=();エッジ[I] .V読み取り=();エッジ[I] .A)(読み取る。=、エッジ[i]は.Bは。= 読み取ります( ); エッジ[I + 1 ] .U =エッジ[I] .U、エッジ[I + 1 ] .V =エッジ[I] .V、エッジ[I + 1 ] .A =エッジ[I] .A、エッジ[I + 1 ] .B = エッジ[I] .B。 } INT union_find(INT X){ 場合(X == FA [X])戻りX。 他 戻り FA [X] = union_find(FA [X])。 } 無効アップデート(int型X){ ノード[X] .MAX =のX。 INTの LSON =ノード[X] .son [ 0 ]、rson =ノード[X] .son [ 1 ]。 もし(LSON &&ノード[ノード[LSON] .MAX] .val>ノード[ノード[X] .MAX] .val)ノード[X] .MAX = ノード[LSON] .MAX。 もし(rson &&ノード[ノード[rson] .MAX] .val>ノード[ノード[X] .MAX] .val)ノード[X] .MAX = ノード[rson] .MAX。 } ボイドプッシュダウン(int型X){ 場合(ノード[X] .flag_reverse){ int型 LSON =ノード[X] .son [ 0 ]、rson =ノード[X] .son [ 1 ]。 ノード[LSON] .flag_reverse ^ = 1つの ; ノード[rson] .flag_reverse ^ = 1 ; ノード[X] .flag_reverse ^ = 1 ; スワップ(ノード[X] .son [ 0 ]、ノード[X] .son [ 1 ])。 } } int型 GET(int型x)は{ 返す X ==ノード[ノード[X]の.Fa] .son [ 0 ] || X ==ノード[ノード[X]の.Fa] .son [ 1 ]。 } int型のチェック(int型X){ 戻り X ==ノード[ノード[X]の.Fa] .son [ 1 ]。 } ボイド回転(INT X){ int型Y =ノード[X]の.Fa、Z =ノード[Y]の.Fa、D =チェック(X)、XX =ノード[X] .son [D ^ 1 ]。 ノード[Y] .son [D] = XXを、もし(XX)ノード[XX]の.Fa = Y。 もし(取得(Y))ノード[Z] .son [チェック(Y)] = xと、ノード[X]の.Fa = Z。 ノード[X] .son [D ^ 1 ] = Y;ノード[Y]の.Fa =のX。 アップデート(Y)、更新(X)。 } ボイドスプレイ(INT X){ int型、Y = Xの、トップ= 0 ; STKの[++トップは] = yと、 一方、(取得(Y))STKの[++トップ] = Y = ノード[Y]の.Fa。 一方(上部)プッシュダウン(STK [top-- ])。 同時に(取得{(x))を int型 Y = ノード[X]の.Fa。 もし(取得(Y)) 回転(チェック(X) ==チェック(Y)?Y:X); (x)は、回転、 } } ボイドアクセス(INT X){ int型 XX = 0 。 一方、(X){ スプレイ(X)。 ノード[X] .son [ 1 ] = XXと、 XX = X。 更新(X)。 X = 節点[X]の.Fa。 } } int型の検索(INT X){ アクセス(X)、スプレイ(x)は、 一方(ノード[X] .son [0 ])はx =ノード[X] .son [ 0 ]。 リターンのx; } 空隙 make_root(INT X){ アクセス(X)、スプレイ(X)。 ノード[X] .flag_reverse ^ = 1 ; } ボイドリンク(int型のx、int型のY){ make_root(X)。もし(!)(Yを見つける= X)ノード[X]の.Fa = Y。 } ボイドスプリット(int型のx、int型のY){ make_root(x)は、アクセス(Y)、スプレイ(Y)。 } ボイドカット(int型のx、int型のY){ スプリット(X、Y) もし()(Yを見つける== X &&ノード[X] .son [!1 ] &&ノード[X]の.Fa == y)は ノード[X]の.Fa =ノードを[Y] .son [ 0 ] = 0 ; } int型の照会(int型のx、int型のY){ スプリット(X、Y) 戻りノード[Y] .MAX。 } ボイドワーク(){ ため(int型 I = 1 ; I <= M; ++ i)は、FA [I] = I。 以下のために(int型 I = 1 ; I <= M iは++ ){ int型、U =エッジ[I] .U、V = エッジを[I] .V。 もし(union_find(U)==union_find(V)){ int型、T = クエリ(U、V)。 もし(エッジ[I] .B < ノード[T] .val){ カット(T、エッジ[T - N] .U)。 カット(T、エッジ[T - N] .V)。 } 他{ 場合(union_find(1)== union_find(N)) ANS =分(ANS、エッジ[I] .A +ノード[クエリ(1 、N)]のVal); 続け; } } 他の FA [union_find(U)] = union_find(V)。 ノード[iが+ N] .MAX = iがN +、ノード[iがn] .val = + エッジ[I] .Bと、 リンク(U、iは N +)、リンク(私を+ N、V)。 もし(union_find(1)== union_find(N)) ANS =分(ANS、エッジ[I] .A +ノード[クエリ(1 、N)]のVal); } 場合(ANS =!0x3f3f3f ) のprintf(" %dの" 、ANS)。 他 のprintf(" -1 " ); } BOOL CMP(エッジA、エッジB){ 戻り Aaの< Baのを、 } INT {main()の N= READ(); M =読み取る(); M << = 1 。 以下のために(int型私= 1 ; I <= M; iが+ = 2 )readIn(I)。 ソート(エッジ + 1、エッジ+ M + 1 、CMP)。 作業(); リターン 0 ; }