典型的求最小生成树的题目,采用kruskal算法即可,先存储所有的点,然后分别计算点与点之间的距离,并存储起来,在直接运用kruskal算法即可。唯一需要注意的是输出格式问题。代码如下:
/*
ID: csuchenan
PROG: uva10034Freckles
LANG: C++
*/
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
using namespace std ;
const int maxn = 105 ;
struct Point
{
double x ;
double y ;
}point[maxn] ;
struct Edge
{
int x ;
int y ;
double dist ;
}edge[5000] ;
int parent[maxn] ;
double distance_point ( Point x , Point y)
{
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y)) ;
}
int cmp(const void * a , const void * b)
{
return (*(Edge *)a).dist > (*(Edge *)b).dist ;
}
double kruskal() ;
void init() ;
int find_x(int x) ;
void join(int x , int y) ;
int num ;
int nnum ;
int main()
{
// freopen("10034.in" , "r" , stdin) ;
int tests ;
scanf("%d" , &tests) ;
while(tests--)
{
scanf("%d" , &num) ;
int i ;
i = 0 ;
while(i < num)
{
scanf("%lf %lf" , &point[i].x , &point[i].y) ;
i ++ ;
}
int j ;
int k ;
k = 0 ;
for(i = 0 ; i < num ; i ++)
{
for(j = i + 1 ; j < num ; j ++)
{
edge[k].x = i ;
edge[k].y = j ;
edge[k].dist = distance_point(point[i] , point[j]) ;
k ++ ;
}
}
nnum = k ;
printf("%.2f\n" , kruskal()) ;
if(tests >= 1)
printf("\n") ;
}
return 0 ;
}
void init()
{
int i ;
for(i = 0 ; i < num ; i ++)
{
parent[i] = i ;
}
}
int find_x(int x)
{
int r = x ;
while(r != parent[r])
r = parent[r] ;
int i ;
int j ;
for(i = x ; i != r ;)
{
j = parent[i] ;
parent[i] = r ;
i = j ;
}
return r ;
}
void join(int x , int y)
{
int p = find_x(x) ;
int q = find_x(y) ;
if(p < q)
parent[q] = p ;
else
parent[p] = q ;
}
double kruskal()
{
init() ;
qsort(edge , nnum , sizeof(edge[0]) , cmp) ;
double sum ;
sum = 0.0 ;
int i ;
for(i = 0 ; i < nnum ; i ++)
{
if(find_x(edge[i].x) != find_x(edge[i].y) )
{
sum += edge[i].dist ;
join(edge[i].x , edge[i].y) ;
}
}
return sum ;
}