这题目,笔者认为是出题者还是手软了,出了难度稍微低了点,因为点限制在了100以内,算算两重for循环也不会超时,可以算出一个一个点的距离,而不需要用分治法,嘿嘿.
主要的易错点就是那个<10和>1000的情况.开始的情况我也考虑错了,因为我觉得一出现10,或者1000就可以断定这个无法完成,
但是,不是这样的.假设有无数个点,第一个点跟最后一个点无穷远,但你可不能把这种情况给删除了,虽然你无穷远,但是有无穷个点呀....嘿嘿,开个玩笑了,就是要提醒你,
所以,笔者认为,遇到<10或者>1000的时候,可以暂且吧这些特殊的点赋成inf,暂且不用,等并查集的时候咱们在判定,如果除了了这些inf没有形成通路,那么就可以打印出"oh!"了
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define inf 0x3fffffff
int T,N;//T represents the number of dates,and N represents the number of points;
int set[110];
int kk;//kk represents the number of edges;
int flag;
struct Edge
{
int a;
int b;
double len;
}e[15000];
struct point
{
int x;
int y;
}head[105];
double Lenth(int x1,int x2,int y1,int y2)
{
return sqrt((x2-x1)*(x2-x1)*1.0+(y2-y1)*(y2-y1)*1.0);
}
int find(int x)
{
return set[x]=(set[x]==x?x:find(set[x]));
}
int cmp(const void *a,const void *b)
{
Edge *x=(Edge *)a,*y=(Edge *)b;
return x->len-y->len>0?1:-1;
}
void kruskal()
{
for(int i=1;i<=N;i++)
{
set[i]=i;
}
double temp=0;
for(i=0;i<kk;i++)
{
int x=find(e[i].a),y=find(e[i].b);
double val=e[i].len;
if(x!=y)
{
set[x]=y;
if(val==inf)
flag=0;
temp+=val;
}
}
if(flag)
printf("%.1lf\n",temp*100);
else
printf("oh!\n");
}
int main()
{
while(scanf("%d",&T)!=EOF)
{
while(T--)
{
kk=0;
flag=1;
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
scanf("%d%d",&head[i].x,&head[i].y);
}
for(int j=1;j<N;j++)
{
for(i=j+1;i<=N;i++)
{
e[kk].a=j;
e[kk].b=i;
e[kk].len=Lenth(head[i].x,head[j].x,head[i].y,head[j].y);
if(e[kk].len<10||e[kk].len>1000)
{
// printf("%lf\n",e[kk].len);
e[kk].len=inf;
}
kk++;
}
}
// printf("%d\n",kk);
qsort(e,kk,sizeof(e[0]),cmp);
//for(int k=0;k<kk;k++)
// printf("%lf ",e[k].len);
// printf("\n");
kruskal();
}
}
return 0;
}