[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;
}
posted @ 2021-05-23 15:12  dfydn  阅读(39)  评论(0编辑  收藏  举报