ファーマージョンはちょうどいくつかの新しいファームを取得していました!彼は道路の配列を介して、他のファームに任意のファームから移動することができるように道路に農場を接続したいです。道路はすでに農場の一部を接続します。
ファーム(好都合番号1..N)Nのそれぞれ(千≤1≤N)が平面上の位置(XI、李)で表される(0≤Xiの≤1,000,000; 0イー≤1,000,000以下)。接続されている農場の対として既存のM道路(千≤1≤M)を考えると、ファーマージョンは彼がすべての彼の農場を接続するために構築する必要があり、追加の道路の最小の長さを決定するのに役立ちます。
ファーマージョンは最近、いくつかの新しいファームを持って、彼はすべての道路の一部の相互運用を終了するには彼の農場は、既存または新規の道路の端を渡すことができるように新しい道路の一部を修復したい(つまり、いずれかのファームから通過することができます)農場のすべての残りの部分に達します。もともといくつかの農場間の道路にあり接続されていました。すべてのN(1 <= N <=千)ファーム(順次番号1..N有する)は、座標(X_I、Y_I)点(0 <= X_I <= 1,000,000の地図として表され、0 <= Y_I <= 1,000,000)と、2つのファームの性質との間の道路の長さは、その点間の距離を表します。今ファーマージョンはまた、2つの農場を接続した農道の間、元のM(1 <= M <= 1,000)告げ、彼はあなたが数学を行う期待している、すべてのファームの接続を行うために、彼は道路を構築する必要があります最小の全体の長さです。
入力形式
* 1行目:二スペースで区切られた整数:NとM
*行2..N + 1:二つのスペースで区切られた整数:西と李
*行N + 2..N + M + 2:二つのスペースで区切られた整数:iとj、ファームi及びファームjを結ぶ道路が既に存在することを示します。
1行目:2スペースで区切られた整数で:NとM
まず2..N + 1:スペースで区切られた2行I + 1の行為整数:X_I、Y_I
第N + 2..N + M + 2行:i、jは、既存の道路、I jの農場および牧場を結ぶ道路を記述する空間の整数で区切られた各ラインを有する2
出力フォーマット
* 1行目:すべての農場を接続するために必要な追加の道路の最小の長さは、小数点第3位を四捨五入せずに印刷。64ビットの浮動小数点数として距離を算出するようにしてください。
すべてのファーム出力接続は、任意の付加的な丸め演算を実行することなく、道路工事、小数点以下2桁の最小合計長さを必要としました。ファームと回答との間の距離を算出する際の精度誤差を回避するために、64ビットの実変数を使用
サンプル入力と出力
入力#14 1 1 1 3 1 2 3 4 3 1 4出力#14.00説明/ヒント
説明タイトル:通信ポイントを有するいくつかのn個の点の座標を、指定された、すべての点は、現在、道路の必要最小限の長さを通信しようとしています。
(ロス・バレーから)
必要な最小の長さのポイントユニコム直接最小スパニングツリーのすべてのため。
パスの一部が修復されているように、それはもはや(確かに、ツリー内の重み付けされた値なし)修理しないので、各経路は直接のための右側を追加ゼロであることができます。
Iはベクトル記憶パスを使用する、徹底的各2つの点のユークリッド距離の挿入側を求めるには、それらの0辺の重みを直接クラスカル法を解決した後、最後に参加します。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 int型M、N。 ダブルRSLT。 ダブル POSX [ 1010 ]、POSY [ 1010 ]; 構造体縁{ INT からの、。 ダブルのval; }。 ベクター <エッジ> G。 int型のedge_cnt。 BOOL CMP(CONSTエッジ&X、CONSTエッジ&Y){ 場合(x.val == y.val){ 場合(X。から == yを。から)リターンx.to < y.to。 返すのxを。<Y。から; } 戻り x.val < y.val。 } ボイド add_edge(int型の F、int型の T、ダブルV){ g.push_back((エッジ){F、T、V})。 g.push_back((エッジ){T、F、V})。 edge_cnt + = 2 ; } int型の父[ 1010 ]。 int型の検索(int型x)は{ 場合(!父[X] = x)の父[X] = 見つける(父[X]); 返す父を[X]; } ボイドadd_place(){ ため(int型 i = 1 ; iがN <、iは++ ){ ための(int型 J = iは+ 1、J <= nであり、j ++ ){ ダブル LEN =(ダブル)SQRT((ダブル)(POSX [I ] - POSX [J])*(POSX [I] - POSX [J])+(ダブル)(POSY [I] - POSY [J])*(POSY [I] - POSY [J]))。 add_edge(I、J、LEN); } } を返します。 } ボイドクラスカル(){ ため(int型 i = 0 ; iがn <; iは++ ){ 父[i]は = 私; } ソート(g.begin()、g.end()、CMP)。 int型のCNT; 以下のために(int型私= 0 ; iがedge_cntを<; Iは++ ){ int型 F1 =検索(G [I] から)、F2 = 検索(G [i]の.TO)。 もし(!F1 = F2){ RSLT + = G [i]は.val。 父[F1] = F2; もし(++ CNT == N- 1)のリターン; } } } int型{main()の // freopenは(STDIN、 "R"、 "です。"); // freopenは( "W"、STDOUT "アウト"); CIN >> N >> M。 以下のために(int型 i = 1 ; iが<= N; iは++ ){ CIN >> POSX [I] >> POSY [I]。 } add_place()。 以下のために(int型 i = 0 ; iがm <Iは、++は){ int型、F、T。 CIN >> F >> トン。 add_edge(F、T、0 ); } クラスカル()。 printf(" %の.2f " 、RSLT)。 リターン 0; }