一个普通的最小生成树问题,kruskal算法或prim算法解决,我用的kruskal,因为目前我只会这个。题目意思是给你那什么长在身上的雀斑的坐标,然后问你能够使每个雀斑都连在一起所需要的最少油墨长度。
kruskal解法:首先要把每两个点构成的边的边长计算出来,然后把这些边按照长度由小到大来排序,把边从小到大一次加入最小生成树中,如果加入的边会构成环的话就不加入(并查集实现,当边上的两点属于同一集合就说明加入后会构成环),最后输出这些边的总长度就可以了。
注意:我的代码在c和c++编译器中能通过,在gcc和g++编译器中则会WA,因为在gcc和g++中double类型的输出是%f,也就是说将输出改成%f在gcc和g++就能通过,而在c和c++则依旧能通过,说明%f用来输出double类型在这些编译器中都是可以的。(感觉有点反常理,但事实是这样、、、)
下面附上我的解题代码,kruskal算法:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 110
typedef struct point //定义点的结构体
{
double x, y; //坐标
}point;
typedef struct side //定义边的结构体
{
int a, b; //两点的下标
double len; //边长
}side;
point p[N];
side s[N*N];
int bleg[N]; //存储父节点
int pn; //点的数量
int sn = 0; //边的数量
double ans = 0; //答案
void Init(); //初始化
void Read(); //输入点并且计算边
double Count(int x, int y); //计算边长
int Find(int x); //查找操作,用于判断是否成环
void Union(int x, int y); //合并操作
int Mycompare(const void *a, const void *b); //用于qsort的排序比较函数
void Link(); //将边连接起来构造并计算最小生成树
int main()
{
scanf("%d", &pn);
Init();
Read();
qsort(s, sn, sizeof(s[0]), Mycompare);
Link();
printf("%.2lf\n", ans); //如果输出为%.2f的话则在以上4种编译器中都能通过
return 0;
}
void Init() //初始化
{
int i;
for (i=0; i<N; ++i)
{
bleg[i] = i;
}
ans = 0;
return;
}
void Read() //输入点并且计算边
{
int i, j;
for (i=0; i<pn; ++i)
{
scanf("%lf %lf", &p[i].x, &p[i].y);
for (j=0; j<i; ++j) //开始计算边的信息
{
s[sn].a = i;
s[sn].b = j;
s[sn++].len = Count(i, j);
}
}
return;
}
double Count(int x, int y) //计算边长
{
double lx = (p[x].x - p[y].x) * (p[x].x - p[y].x);
double ly = (p[x].y - p[y].y) * (p[x].y - p[y].y);
double len = sqrt(lx + ly);
return len;
}
int Find(int x) //查找操作,用于判断是否成环
{
int y = bleg[x];
int z;
while (y != bleg[y])
{
y = bleg[y];
}
while (x != bleg[x])
{
z = bleg[x];
bleg[x] = y;
x = z;
}
return y;
}
void Union(int x, int y) //合并操作
{
int fx = Find(x);
int fy = Find(y);
bleg[fx] = fy;
return;
}
int Mycompare(const void *a, const void *b) //用于qsort的排序比较函数
{
if ((*(side *)a).len > (*(side *)b).len)
{
return 1;
}
return -1;
}
void Link() //将边连接起来构造并计算最小生成树
{
int i;
for (i=0; i<sn; i++)
{
if (Find(s[i].a) != Find(s[i].b))
{
Union(s[i].a, s[i].b);
ans += s[i].len;
}
}
return;
}