题意
给出n个点的坐标,若两点间距离满足大于等于10小于等于1000,则可以建桥。求使得所有桥联通最少需要花费多少钱(100元/m)
思路
把题中给出的坐标信息,提取成边的信息,就是到最小生成树的模板题,用克鲁斯卡尔算法即可解决。
边的范围开大一点,开小了可能报超时
代码
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 120
int t,n,f[N];
struct edge { //存坐标
double x,y;
} e[N];
struct node { //存边
int a,b;
double c;
} m[100*N]; //不要开太小!!!
bool cmp(node x,node y) {
return x.c<y.c;
}
double dist(edge a,edge b) {
return sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2));
}
int getf(int x) {
if(f[x]==x) return x;
return f[x]=getf(f[x]);
}
int main() {
scanf("%d",&t);
while(t--) {
while(~scanf("%d",&n)) {
for(int i=1; i<=n; i++)
scanf("%lf%lf",&e[i].x,&e[i].y);
//提取边
int k=1;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++) {
double tem=dist(e[i],e[j]); //只存合适的边
if(tem>=10&&tem<=1000) {
m[k].a=i;
m[k].b=j;
m[k++].c=tem;
}
}
sort(m+1,m+1+k,cmp);
//克鲁斯卡尔~
double sum=0;
for(int i=1; i<=n; i++) f[i]=i;
for(int i=1; i<=k; i++) {
int t1=getf(m[i].a);
int t2=getf(m[i].b);
if(t1!=t2) {
f[t2]=t1;
sum+=m[i].c;
}
}
int ans=0;
for(int i=1; i<=n; i++)
if(f[i]==i) ans++;
if(ans==1)
printf("%.1f\n",sum*100);
else printf("oh!\n");
}
}
return 0;
}