题目描述
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.
给出nn个点的坐标,其中一些点已经连通,现在要把所有点连通,求修路的最小长度.
输入输出格式
输入格式:-
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.
- 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.
输入输出样例
1 1
3 1
2 3
4 3
1 4
其实就是最小生成树的题。。水水。。
首先n个点(n只有1000...)给出坐标,直接可以暴力求出两两点之间的距离的。
考虑用克鲁斯卡尔算法,首先排个序,然后……
对于m个已经连起来的点,在一开始用并查集连起来就好了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
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;
}
const int
N=1005;
int n,m,len;
int x[N],y[N],fa[N];
struct Map{
double di;
int x,y;
}ma[N*N>>1];
bool cmp(Map x,Map y){
return x.di<y.di;
}
double dis(int a,int b){
return (double)sqrt((double)((ll)(x[b]-x[a])*(ll)(x[b]-x[a])+(ll)(y[b]-y[a])*(ll)(y[b]-y[a])));
}
int getfa(int x){
if (x!=fa[x]) fa[x]=getfa(fa[x]);
return fa[x];
}
void unn(int x,int y){
int t1=getfa(x),t2=getfa(y);
if (t1!=t2) fa[t2]=t1;
}
int main(){
n=read(),m=read();
for (int i=1;i<=n;i++) x[i]=read(),y[i]=read();
len=0;
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++)
ma[++len].di=dis(i,j),ma[len].x=i,ma[len].y=j;
int t1,t2;
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++) t1=read(),t2=read(),unn(t1,t2);
sort(ma+1,ma+1+len,cmp);
double ans=0.0;
for (int i=1;i<=len;i++){
int t1=ma[i].x,t2=ma[i].y;
int f1=getfa(t1),f2=getfa(t2);
if (f1==f2) continue;
unn(f1,f2);
ans+=ma[i].di;
}
printf("%.2lf\n",ans);
return 0;
}