题目描述
Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.
Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1…N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.
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)条路分别连接了哪两个农场,他希望你计算一下,为了使得所有农场连通,他所需建造道路的最小总长是多少。
输入格式
-
Line 1: Two space-separated integers: N and M
-
Lines 2…N+1: Two space-separated integers: Xi and Yi
-
Lines N+2…N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.
第1行: 2个用空格隔开的整数:N 和 M
第2…N+1行: 第i+1行为2个用空格隔开的整数:X_i、Y_i
第N+2…N+M+2行: 每行用2个以空格隔开的整数i、j描述了一条已有的道路, 这条道路连接了农场i和农场j
输出格式
- Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.
输出使所有农场连通所需建设道路的最小总长,保留2位小数,不必做 任何额外的取整操作。为了避免精度误差,计算农场间距离及答案时 请使用64位实型变量
题解
尼玛一个普及/提高-的题,卡尼玛的精度,爷吐了,最小生成树模板乱搞就行(还是kruskal香)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#define inf 2000000000
using namespace std;
const int M=5000105;
const int N=1006;
int n,m,zong;
int fa[N];
struct NODE{
int x,y;
}dian[N];
struct Node{
int x,y;
double z;
bool operator < (const Node &a){
return this->z < a.z;
}
}bian[M*2];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline double cal(int a,int b){
//注意这个,卡精度
return (double)(sqrt((double)(dian[a].x-dian[b].x)*(dian[a].x-dian[b].x)+(double)(dian[a].y-dian[b].y)*(dian[a].y-dian[b].y)));
}
int find(int x){
if(fa[x]==x) return x;
return find(fa[x]);
}
inline void init(){
zong=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
zong++;
bian[zong].x=i;
bian[zong].y=j;
bian[zong].z=cal(i,j);
}
}
return ;
}
inline void kruskal(){
sort(bian+1,bian+zong+1);
int tot=0;
double ans=0.000000000000;
for(int i=1;i<=zong;i++){
if(fa[find(bian[i].x)]!=fa[find(bian[i].y)]){
fa[find(bian[i].x)]=fa[find(bian[i].y)];
ans+=bian[i].z;
tot++;
}
if(tot>=n-1){
printf("%.2lf",ans);
break;
}
}
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=n;i++) dian[i].x=read(),dian[i].y=read();
init();
for(int i=1;i<=m;i++){
int x,y;
x=read();y=read();
bian[++zong].x=x;
bian[zong].y=y;
bian[zong].z=0.00;
}
kruskal();
return 0;
}