1. 程式人生 > >公路修建

公路修建

virtual turn efault bbs 解決 status temp icpc lin

問題 H: 【圖】公路修建

時間限制: 5 Sec 內存限制: 128 MB
提交: 12 解決: 6
[提交] [狀態] [討論版] [命題人:admin]

題目描述

某國有n個城市,它們互相之間沒有公路相通,因此交通十分不便。為解決這一“行路難”的問題,政府決定修建公路。修建公路的任務由各城市共同完成。
修建工程分若幹輪完成。在每一輪中,每個城市選擇一個與它最近的城市,申請修建通往該城市的公路。政府負責審批這些申請以決定是否同意修建。
政府審批的規則如下:
(1)如果兩個或以上城市申請修建同一條公路,則讓它們共同修建;
(2)如果三個或以上的城市申請修建的公路成環。如下圖,A申請修建公路AB,B申請修建公路BC,C申請修建公路CA。則政府將否決其中最短的一條公路的修建申請;
技術分享圖片 (3)其他情況的申請一律同意。
一輪修建結束後,可能會有若幹城市可以通過公路直接或間接相連。這些可以互相:連通的城市即組成“城市聯盟”。在下一輪修建中,每個“城市聯盟”將被看作一個城市,發揮一個城市的作用。
當所有城市被組合成一個“城市聯盟”時,修建工程也就完成了。
你的任務是根據城市的分布和前面講到的規則,計算出將要修建的公路總長度。

輸入

第一行一個整數n,表示城市的數量。(n≤5000)
以下n行,每行兩個整數x和y,表示一個城市的坐標。(-1000000≤x,y≤1000000)

輸出

一個實數,四舍五入保留兩位小數,表示公路總長。(保證有惟一解)

樣例輸入

4
0 0
1 2
-1 2
0 4

樣例輸出

6.47
思路:因為每個城市找到都是最短的,因此不可能成環,直接跑最小生成樹,註意數據比較大,鄰接矩陣顯然不行,所以走一波prim。
#include<bits/stdc++.h>
using namespace std;
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define
PER(i, a, b) for(int i = (a); i >= (b); -- i) template <class T> inline void rd(T &ret) { char c; ret = 0; while ((c = getchar()) < 0 || c > 9); while (c >= 0 && c <= 9) { ret = ret * 10 + (c - 0), c = getchar(); } } const int maxn = 5e3 + 10; int n, u[maxn], v[maxn], vis[maxn]; double ans; double dis[maxn]; int main() { rd(n); for (int i = 1; i <= n; i++) { cin>>u[i]>>v[i]; dis[i] = 0x3f3f3f3f; } dis[1] = 0; REP(i, 1, n) { double cur = 0x3f3f3f3f; int gt; REP(j, 1, n) { if (!vis[j] && dis[j] < cur) { cur = dis[j], gt = j; } } if (cur == 0x3f3f3f3f)break; vis[gt] = 1; ans += dis[gt]; REP(j, 1, n) { double r = sqrt(double(u[gt] - u[j])*(u[gt] - u[j]) + (double)(v[gt] - v[j])*(v[gt] - v[j])); if (r < dis[j])dis[j] = r; } } printf("%.2f", ans); return 0; }

 

公路修建