[USACO14MAR]Watering the Fields S
欧几里得距离不需要开根号,题目描述联通的最小代价指的是和。
细节:
1.因为克鲁斯卡尔算法枚举的是边,所以不需要在意是无向图,仅存一遍即可,即32、33行,j直接从i+1开始枚举。
2.最后判断时,如果tot==n-1,让其break,再外面再进行其他操作会更快一些。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2005;
int n,c,tot,cnt,ans;
struct node{
int x,y;
}a[N];
int f[N];
struct Node{
int x,y;
int w;
}edge[N*N];
bool cmp(Node a,Node b){
return a.w<b.w;
}
int find(int x){
if(x==f[x]) return x;
return f[x]=find(f[x]);
}
int main(){
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++){
int u,v;
scanf("%d%d",&u,&v);
a[i].x=u; a[i].y=v;
}
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
int tmp=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
if(tmp>=c){
edge[++cnt].x=i; edge[cnt].y=j; edge[cnt].w=tmp;
}
}
sort(edge+1,edge+cnt+1,cmp);
for(int i=1;i<=cnt;i++){
int r1=find(edge[i].x);
int r2=find(edge[i].y);
if(r1==r2) continue;
f[r1]=r2;
tot++;
ans+=edge[i].w;
if(tot==n-1) break;
}
if(tot==n-1){
printf("%d",ans);
}
else printf("-1");
return 0;
}