JZOJ 1244. 修建道路

时间:2019-11-08
本文章向大家介绍JZOJ 1244. 修建道路,主要包括JZOJ 1244. 修建道路使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

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

Sample Output

4.00
 

Data Constraint

 
 

Hint

样例说明:
FJ选择在农场1和农场2间建一条长度为2.00的道路,在农场3和农场4间建一条长度为2.00的道路。这样,所建道路的总长为4.00,并且这是所有方案中道路总长最小的一种。

 

分析

 

  • 首先连通图 肯定是树啦
  • 不就是最小生成树吗
  • 然后我们把一些已经存在的边赋值为0
  • 跑出来就是ans

代码

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #define ll long long
 7 using namespace std;
 8 struct sb
 9 {
10     int x,y;
11 }a[2001];
12 struct A
13 {
14     int from,to; double val;
15 }e[1000001];
16 int map[1001][1001];
17 double calc(int x1,int x2)
18 {
19     double ans=sqrt((double)(a[x1].x-a[x2].x)*(a[x1].x-a[x2].x)+(double)(a[x1].y-a[x2].y)*(a[x1].y-a[x2].y));
20     return ans;
21 }
22 int fa[1001];
23 bool cmp(A a,A b){return a.val<b.val;}
24 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} 
25 int main()
26 {
27     int n,m;
28     scanf("%d%d",&n,&m);
29     for (int i=1,xx,yy;i<=n;i++)
30     {
31         scanf("%d%d",&xx,&yy);
32         a[i].x=xx; a[i].y=yy;
33     }
34     int tot=0;
35     for (int i=1,x,y;i<=m;i++)
36     {
37         scanf("%d%d",&x,&y);
38         e[++tot].from=x; e[tot].to=y; e[tot].val=0;
39         map[x][y]=1;
40     }
41     for (int i=1;i<n;i++)
42       for (int j=i+1;j<=n;j++)
43       {
44            if (i==j||map[i][j]==1) continue;
45            e[++tot].from=i; e[tot].to=j; e[tot].val=calc(i,j);
46       }
47     sort(e+1,e+1+tot,cmp);
48     for (int i=1;i<=n;i++) fa[i]=i;
49     double ans=0;
50     int cnt=0;
51     for (int i=1;i<=tot&&cnt<n-1;i++)
52     {
53         int u=find(e[i].from),v=find(e[i].to);
54         if (u==v) continue;
55         ans+=e[i].val,cnt++,fa[u]=v;
56     }
57     printf("%.2f",ans);
58     return 0;
59 }

原文地址:https://www.cnblogs.com/zjzjzj/p/11821097.html