1626: [Usaco2007 Dec]Building Roads 修建道路
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1724 Solved: 725
[Submit][Status][Discuss]
Description
Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场)。有些农场之间原本就有道路相连。 所有N(1 <= N <= 1,000)个农场(用1..N顺次编号)在地图上都表示为坐标为(X_i, Y_i)的点(0 <= X_i <= 1,000,000;0 <= Y_i <= 1,000,000),两个农场间道路的长度自然就是代表它们的点之间的距离。现在Farmer John也告诉了你农场间原有的M(1 <= M <= 1,000)条路分别连接了哪两个农场,他希望你计算一下,为了使得所有农场连通,他所需建造道路的最小总长是多少。
Input
* 第1行: 2个用空格隔开的整数:N 和 M
* 第2..N+1行: 第i+1行为2个用空格隔开的整数:X_i、Y_i * 第N+2..N+M+2行: 每行用2个以空格隔开的整数i、j描述了一条已有的道路, 这条道路连接了农场i和农场j
Output
* 第1行: 输出使所有农场连通所需建设道路的最小总长,保留2位小数,不必做 任何额外的取整操作。为了避免精度误差,计算农场间距离及答案时 请使用64位实型变量
Sample Input
4 1
1 1
3 1
2 3
4 3
1 4
输入说明:
FJ一共有4个坐标分别为(1,1),(3,1),(2,3),(4,3)的农场。农场1和农场
4之间原本就有道路相连。
1 1
3 1
2 3
4 3
1 4
输入说明:
FJ一共有4个坐标分别为(1,1),(3,1),(2,3),(4,3)的农场。农场1和农场
4之间原本就有道路相连。
Sample Output
4.00
输出说明:
FJ选择在农场1和农场2间建一条长度为2.00的道路,在农场3和农场4间建一
条长度为2.00的道路。这样,所建道路的总长为4.00,并且这是所有方案中道路
总长最小的一种。
输出说明:
FJ选择在农场1和农场2间建一条长度为2.00的道路,在农场3和农场4间建一
条长度为2.00的道路。这样,所建道路的总长为4.00,并且这是所有方案中道路
总长最小的一种。
HINT
Source
Analysis
最小生成树的水题
如果有一些农场已经互相连接了 -- 那就提前 unite
注意计算坐标时是否溢出
Code
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #define maxn 2000 6 using namespace std; 7 8 int n,m,x[maxn],y[maxn]; 9 10 int pre[maxn]; 11 int find(int x){ 12 if(!pre[x]) return x; 13 else{ 14 pre[x] = find(pre[x]); 15 return pre[x]; 16 } 17 }void unite(int a,int b){ 18 if(find(a) != find(b)) pre[find(a)] = find(b); 19 } 20 21 struct edge{ 22 int u,v; 23 double len; 24 }e[maxn*maxn]; 25 26 int tot; 27 void insert(int u,int v,double len){ 28 tot++; 29 e[tot].u = u; 30 e[tot].v = v; 31 e[tot].len = len; 32 } 33 34 double getdis(int a,int b){ 35 return sqrt(1LL*(x[a]-x[b])*(x[a]-x[b])+1LL*(y[a]-y[b])*(y[a]-y[b])); 36 } 37 38 bool cmp(const edge &a,const edge &b){ 39 return a.len < b.len; 40 } 41 42 void kruskal(){ 43 sort(e+1,e+1+tot,cmp); 44 45 double ans = 0; 46 47 for(int i = 1;i <= tot;i++){ 48 int u = e[i].u,v = e[i].v; 49 if(find(u) != find(v)){ 50 unite(u,v); 51 ans += e[i].len; 52 } 53 } 54 55 printf("%.2lf",ans); 56 } 57 58 int main(){ 59 scanf("%d%d",&n,&m); 60 61 for(int i = 1;i <= n;i++){ 62 scanf("%d%d",&x[i],&y[i]); 63 } 64 65 for(int i = 1;i <= m;i++){ 66 int a,b; 67 scanf("%d%d",&a,&b); 68 unite(a,b); 69 } 70 71 for(int i = 1;i <= n;i++){ 72 for(int j = i+1;j <= n;j++){ 73 if(find(i) != find(j)){ 74 insert(i,j,getdis(i,j)); 75 } 76 } 77 } 78 79 kruskal(); 80 81 return 0; 82 }