HDU 1875 畅通工程再续 最小生成树问题

时间:2023-03-09 03:54:13
HDU 1875 畅通工程再续 最小生成树问题

题目描述:输入一个T,表示有T组测试数据,然后每组测试数据有一个C,表示在一个湖里面有C座岛屿,现在要在岛屿之间修建桥,可以修建必须满足的条件是岛与岛之间的距离在10到1000的范围内,然后给出每座岛屿的坐标,并且每米的修建桥的费用为100,求能把所有岛屿连接起来的所需要的最小费用,如果不能将所有的岛屿联通,则输出oh?

解题报告:比较裸的一道最小生成树,因为有一个判断到底是否存在最小生成树的问题,所以,个人觉得用克鲁斯卡尔比较好,因为要用到并查集,那样就不用再另外写一个并查集了。直接看代码:

 #include<cstdio>
#include<algorithm>
#include<cmath>
const int MAX = +;
double map[MAX][MAX],loc[MAX][];
struct node {
int x,y;
double length;
}rode[MAX];
bool cmp(node a,node b) { //比较函数
return a.length<b.length;
}
int T,C,prim[MAX];
double distan(double x1,double y1,double x2,double y2) { //求两岛屿之间的距离
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int find(int k) { //并查集
return prim[k]==k? k:prim[k] = find(prim[k]);
}
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&C);
for(int i = ;i<=C;++i)
scanf("%lf%lf",&loc[i][],&loc[i][]);
int k = ;
for(int i = ;i<=C;++i)
for(int j = i+;j<=C;++j) { //将距离转换成边
double dis = distan(loc[i][],loc[i][],loc[j][],loc[j][]);
if(dis<=&&dis>=)
rode[++k].x = i,rode[k].y = j,rode[k].length = dis;
}
std::sort(rode+,rode+k+,cmp);
double sum = ;
for(int i = ;i<=C;++i)
prim[i] = i;
for(int i = ;i<=k;++i)
if(find(rode[i].x)!=find(rode[i].y)) {
prim[find(rode[i].x)] = find(rode[i].y);
sum+=rode[i].length;
}
bool flag = ;
for(int i = ;i<=C;++i) //判断是否存在最小生成树
if(find()!=find(i)) {
flag = ;
break;
}
if(flag) {
printf("oh!\n");
continue;
}
printf("%.1lf\n",100.0*sum);
}
return ;
}