题目的意思给出很多个点,
问把这些点联通起来,最小边长和是多少..
首先把每条边的长度求出来,并且把边的序号 按照边从小到达排序.
这样就首先考虑边长最小的边,把它的两个端点UNION.
AC代码:
#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 100;
struct point {
double x;
double y;
}p[N];
int f[N];
double w[N * N];
int l[N * N];
int r[N * N];
int s[N * N];
int n;
int cmp (int a ,int b) {
return w[a] < w[b];
}
int find(int x) {
return f[x] == x ? x :f[x] = find(f[x]) ;
}
int main () {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
for (int i = 0 ; i < n ;i++) {
f[i] = i;
}
for (int i = 0 ; i < n;i++) {
scanf("%lf%lf",&p[i].x,&p[i].y);
}
int k = 0 ;
for (int i = 0 ; i < n ;i++) {
for (int j = 0 ; j < i ;j++) {
w[k] = sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y));
l[k] = i;
r[k] = j;
k++;
}
}
for (int i = 0 ; i < k ;i++) {
s[i] = i;
}
double sum = 0;
sort(s , s + k ,cmp);
for(int i = 0 ; i < k ;i++) {
int e = s[i];
int x = find(l[e]);
int y = find(r[e]);
if(x != y) {
sum += w[e];
f[x] = y;
}
}
printf("%.2lf\n",sum);
if (t) {
printf("\n");
}
}
}