基本的な考え方bzoj 2594ステップよりも、より多くの
私たちが最初に見つかったものは、財産の二つの側面があるということでしたので、我々は最初の人制限を削除検討します
我々は、すべての小から大への$ $の降順によって側面、その後、最小スパニングツリーのメンテナンスに追加
プラス側の$ B $は操作bzoj 2594のサイズに合わせてあるたびに、その答えを更新することができます
あなたはまだユニコム出力がない場合は-1
書式#include <cstdioを> する#include <cmath> の#include <CStringの> の#include <cstdlib> 書式#include <iostreamの> の#include <アルゴリズム> 書式#include <キュー> の#include <スタック> の#include <マップ> 使用して 名前空間はstd; 構造体QUES { int型X、Y、TYP、NUM。 } Q [ 1000005 ]。 構造体のエッジ { int型のL、R、V1、V2。 フレンドブール 演算子 < (エッジA、エッジB) { リターン?a.v1 == b.v1 a.v2 <b.v2:a.v1 < b.v1。 } }エッジ[ 1000005 ]。 マップ <ペア< int型、int型 >、int型 > M; INTのN、M、Q。 INT CH [ 2000005 ] [ 2 ]。 int型 VIS [ 2000005 ]。 int型 MAXX [ 2000005 ]。 int型のval [ 2000005 ]。 INT [F 2000005 ]。 int型 FL [ 2000005 ]。 int型のRET [ 2000005 ]。 空隙アップデート(INT X) { MAXX [X] = valの[X]。 もし(エッジ[MAXX [CH [X] [ 0 ]]] V2>エッジ[MAXX [X]] V2。)MAXX [X] = MAXX [CH [X] [ 0 ]]。 もし(エッジ[MAXX [CH [X] [ 1 ]]] V2>エッジ[MAXX [X]] V2。)MAXX [X] = MAXX [CH [X] [ 1 ]。 } ブール be_root(INT X) { 場合(CH [F [X]] [ 0 ] == X || CH [F [X]] [ 1 ] == x)をリターン 0 。 リターン 1 ; } ボイドプッシュダウン(int型X) { もし(FL [X]) { スワップ(CH [CH [X] [ 0 ] [ 0 ]、CH [CH [X] [ 0 ] [ 1 ])。 スワップ(CH [CH [X] [ 1 ] [ 0 ]、CH [CH [X] [ 1 ] [ 1 ])。 FL [CH [X] [ 0 ]] ^ = 1、FL [CH [X] [ 1 ] ^ = 1 ; FL [X] = 0 ; } } ボイド repush(INT X) { 場合(!repush(F [X])be_root(X)); プッシュダウン(X)。 } のボイド回転(int型X) { int型、Y = F [X]、Z = F [Y]、K =(CH [Y] [ 1 ] == X) もし(!be_root(Y))CH [Z] [CH [Z] [ 1 ] == Y] =のX。 F [X] = Z; CH [y]は[K] = CHを[X] [K!]、F [CH [X] [] kは!] = yと; CH [X] [ = Y、F [Y] = kを!] X。 アップデート(Y)、更新(X)。 } ボイドスプレイ(INT X) { repush(X)。 一方、(be_root(X)&&!X) { int型、Y = F [X]、Z = F [Y]。 もし(!be_root(Y)&& y)は { もし((CH [Y] [ 1 ] == X)^(CH [Z] [ 1 ] == Y))に回転(X) そうでなければ(Y)を回転させます。 } 回転(X) } 更新(X) } ボイドアクセス(INT X) { int型、Y = 0 。 一方、(X) { スプレイ(X)。 CH [X] [ 1 ] = yと、 更新(X)。 Y = X、X = F [X]。 } } ボイド makeroot(INT X) { アクセス(X)、スプレイ(X)。 スワップ(CH [X] [ 0 ]、CH [X] [ 1 ])、FL [X] ^ = 1 ; } ボイドリンク(int型のx、int型のY) { makeroot(X)。 F [X] = yと、 } ボイドスプリット(int型のx、int型のY) { makeroot(X)、アクセス(Y)、スプレイ(Y)。 } ボイドカット(int型のx、int型のY) { スプリット(x、y)を、CH [Y] [ 0 ] = F [X] = 0 、更新(Y)。 } INT findf(INT X) { アクセス(X)、スプレイ(x)が、プッシュダウン(X)。 一方、(CH [X] [ 0 ])、X = CH [X] [ 0 ]、プッシュダウン(X)。 リターンのx; } インラインint型リード() { int型、F = 1、X = 0。チャー CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ')、F = - 1 ; CH = GETCHAR();} 一方(CH> = ' 0 ' && CH <= ' 9 '){X = X *10 + CH- ' 0 ' ; CH = GETCHAR();} 戻りのx *のF。 } int型のmain() { N =(読み取り)、M = read()は、 用(int型 iは= 1 ; I <= M; iが++ ) { エッジ[I] .L =(読み取り)、エッジ[I] .Rは、read()は、エッジ= [I] .v1 =(読み取り)、エッジ[ i]を.V2 = 読み取ります(); もし(エッジ[I] .L> エッジ[I] .R)スワップ(エッジ[I] .L、エッジ[I] .R)。 } ソート(エッジ + 1、エッジ+ M + 1 )。 int型 ANS = 0x3f3f3f3f 。 以下のために(int型 i = 1 ; iが<= M; iは++)valが[iが+ N] = MAXX [iが+ N] = I。 以下のために(int型 I = 1 ; I <= M iは++ ) { int型 F1 = findf(エッジ[I] .L)、F2 = findfを(エッジ[I] .R)。 もし(F1 == F2) { スプリット(エッジ[I] .L、エッジ[I] .R)。 もし(エッジ[MAXX [エッジ[I] .R] V2> エッジ[I] .V2) { int型 T = MAXX [エッジ[I] .R]。 カット(エッジ[T] .L、T + N)、カット(エッジ[T] .R、T + N)。 リンク(エッジ[I] .L、私 N +)、リンク(エッジ[I] .Rは、iが+ n)を。 } } 他のリンク(エッジ[I] .Lは、iがN +)、リンク(エッジを[I] .R iは+ N)。 INT FF1 = findf(1)、FF2 = findf(N)。 もし(FF1 == FF2) { スプリット(1 、N) ANS =分(ANS、エッジ[i]を.v1 + 。エッジ[MAXX [N] V2)。 } } もし(ANS == 0x3f3f3f3f)のprintf(" -1の\ n " ); 他のprintf(" %d個の\ nを" 、ANS)。 リターン 0 。 }