poj-世界岛
描述
迪拜是富人的天堂。迪拜政府赚钱有高招。他们建造了很多人工海岛出售。这些海岛被建成各大洲的形状,所以统称为“世界岛”。买了这些岛的富豪们都想互相交个朋友,所以他们希望将这些岛用桥连接起来。比尔盖茨也预定了一个岛,但他是唯一一个不想让自己的岛和其他岛相连的富豪,因为他更愿意乘坐他那条参加了二战诺曼底登陆的登陆艇在海上旅行。好在比尔盖茨不在乎哪个岛是留给他的,所以迪拜政府还是能够找到一个建桥的最省钱的办法。最省钱的办法就是要使得桥的总长度最短。总而言之,如果有n个岛,那么他们就应该造n-2座桥连接n-1个岛,然后把剩下的那个孤岛给比尔。比尔随便拿到哪个岛都不会有意见。
请注意:
1) 一个岛可以看做一个点。
2) 一座桥可以看做是连接两个岛的一条线段。
3) 桥和桥只能在岛上相连。
输入
第一行是一个整数,表示测试数据的组数。
每组数据里,第一行是一个整数n,表示岛的数目(0 < n < 50),接下来有n行,每行包含两个整数x和y, ( -20 <= x, y <= 20 ) , 表示一个岛的坐标。
输出
对每组测试数据,输出一行,内容为最省钱建桥方案下所有桥的总长度。结果四舍五入,保留小数点后面2位。
样例输入
2
5
0 0
1 0
18 0
0 1
1 1
3
0 0
1 0
0 1
样例输出
3.00
1.00
解题思路:
并查集,最小生成树。
# include<stdio.h>
# include<math.h>
# include<algorithm>
using namespace std;
struct E
{
int x;
int y;
}po[51];
struct E2
{
int a,b;
double len;
bool operator < (const E2 &h) const
{
return len<h.len;//升序
}
}ed[1300];
int tree[1300];
int find(int x)
{
if(tree[x]==x)
return x;
return find(tree[x]);
}
int main()
{
int t,i,j,k;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
int n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&po[i].x,&po[i].y);
}
double min=123123123;
for(k=0;k<n;k++)
{
int index=0;
for(i=0;i<n;i++)
{
if(k==i) continue;
for(j=0;j<n;j++)
{
if(j==i||j==k) continue;
ed[index].a=i;
ed[index].b=j;
ed[index].len=sqrt(pow(po[i].x-po[j].x,2)+pow(po[i].y-po[j].y,2));
index++;
}
}
/* for(i=0;i<index;i++)
printf("%d %d %.2lf\n",ed[i].a,ed[i].b,ed[i].len);
*/
for(i=0;i<1300;i++)
tree[i]=i;
//排序
sort(ed,ed+index);
double sum=0;
for(j=0;j<index;j++)
{
int a=find(ed[j].a);
int b=find(ed[j].b);
if(a!=b)
{
tree[a]=b;
sum+=ed[j].len;
}
}
if(sum<min)
min=sum;
}
printf("%.2lf\n",min);
}
}
return 0;
}