http://acm.hdu.edu.cn/showproblem.php?pid=1875
本人并查集专题:http://blog.csdn.net/fsafs168/article/details/7801010
/*
* 并查集:这个题说明我掌握的还是不扎实
* 同样的也在说明同一个专题十来道题至少需要
* 本题思路是并查集+贪心
* 首先遍历出所有城市的路径,构造并查集的边集
* 然后根据距离,近的有限,依次并集。(贪心)
* AC了、、、、、
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
struct Node
{
int x;
int y;
}node[200];
struct Map
{
int a;
int b;
double d; //距离
}map[40000];
int father[200];
bool cmp(Map a, Map b)
{
return a.d < b.d;
}
void ini(int n)
{
for(int i=0;i<=n;i++)
{
father[i] = i;
}
}
int find(int x)
{
if(x != father[x])
return find(father[x]);
return father[x];
}
void sert(int a, int b)
{
father[a]= b;
}
void printTest(int m, int n)
{
for(int i=0;i<m;i++)
{
printf("test:%d %d %d %lf\n",i,map[i].a,map[i].b,map[i].d);
}
for(int i=0;i<=n;i++)
{
printf("test:f[%d] :%d\n",i,father[i]);
}
}
double solve(int m)
{
int i,j;
double cost = 0;
for(i=0;i<m;i++)
{
int a = find(map[i].a);
int b = find(map[i].b);
if(a!=b)
{
//printf("aaaaaaaaaaaaa\n");
sert(a,b);
cost += map[i].d;
}
}
cost *= 100;
return cost;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int i,j;
double cost;
int flag = -1;
int m = 0;
for(i=0;i<n;i++)
{
scanf("%d%d",&node[i].x,&node[i].y);
}
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++,m++)
{
map[m].a = i;
map[m].b = j;
map[m].d = sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x)
+(node[i].y-node[j].y)*(node[i].y-node[j].y)*1.0); //距离公式。注意是Double
if(map[m].d<10||map[m].d>1000) //题意中需要舍弃的距离
{
m--;
continue;
}
}
}
ini(n);
sort(map,map+m,cmp);
//printTest(m,n);
cost = solve(m);
for(i=0;i<n;i++)
{
if(i == father[i])
flag++;
}
//printf("test: cost :%.1lf\n",cost);
//printf("flag:%d\n",flag);
if(!flag)
printf("%.1lf\n",cost);
else
printf("oh!\n");
}
return 0;
}