与之前的畅通工程类似,求最小生成树,只是要剔除不符合条件的边,还要判断是否是连通图(这个磨蹭了很长时间,只要判断加入集合的点数与题目给出的点数是否相等即可)。
#include<iostream>
#include<math.h>
#include<algorithm>
#define NUM 103
using namespace std;
struct point
{
int x;
int y;
}pos[NUM];
struct dist
{
int start;
int end;
double val;
}dis[NUM * NUM];
int cmp(const dist &a,const dist &b)
{
return a.val < b.val;
}
double findDistance(struct point a, struct point b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
int set[NUM];
int vex;
void init()
{
for(int i=0;i<=NUM;i++){
set[i]=i;
}
}
int find(int x)
{
int r=x;
while(r!=set[r])
r=set[r];
return r;
}
void merge(int a, int b)
{
int x=find(a);
int y=find(b);
if(x!=y){
set[y]=x;
vex++;//这里是新增的,用于后面判断加入集合的点数与题目给出的点数是否相等
}
}
int isValid(double x)
{
if(x>=10&&x<=1000)
return 1;
else return 0;
}
int main()
{
int t,c,i,j,index,flag;
double sum;
//freopen("C:\\Documents and Settings\\Administrator\\桌面\\input.txt","r",stdin);
cin>>t;
while(t--){
sum=0.0;
flag=0;
init();
cin>>c;
for(i=0;i<c;i++){
cin>>pos[i].x>>pos[i].y;
}
if(c==1){
printf("0.0\n");
continue;
}
index=0;//有效的点数
vex=1;//加入集合中的点数
for(i=0;i<c;i++)
for(j=i+1;j<c;j++){
double mi = findDistance(pos[i],pos[j]);
if(isValid(mi)){
dis[index].start=i;
dis[index].end=j;
dis[index++].val=mi;
}
}
sort(dis,dis+index,cmp);
for(i=0;i<index;i++){
if(find(dis[i].start)!=find(dis[i].end)&&isValid(dis[i].val)){
merge(dis[i].start,dis[i].end);
sum+=dis[i].val;
}
}
if(vex<c)//判断是否连通图
printf("oh!\n");
else printf("%.1lf\n",sum*100);
}
return 0;
}