一个普通的最小生成树问题,kruskal算法或prim算法解决,我用的kruskal,因为目前我只会这个。题目意思是给你那什么长在身上的雀斑的坐标,然后问你能够使每个雀斑都连在一起所需要的最少油墨长度。
kruskal解法:首先要把每两个点构成的边的边长计算出来,然后把这些边按照长度由小到大来排序,把边从小到大一次加入最小生成树中,如果加入的边会构成环的话就不加入(并查集实现,当边上的两点属于同一集合就说明加入后会构成环),最后输出这些边的总长度就可以了。
注意:我的代码在c和c++编译器中能通过,在gcc和g++编译器中则会WA,因为在gcc和g++中double类型的输出是%f,也就是说将输出改成%f在gcc和g++就能通过,而在c和c++则依旧能通过,说明%f用来输出double类型在这些编译器中都是可以的。(感觉有点反常理,但事实是这样、、、)
下面附上我的解题代码,kruskal算法:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <math.h> 4 #define N 110 5 6 typedef struct point //定义点的结构体 7 { 8 double x, y; //坐标 9 }point; 10 typedef struct side //定义边的结构体 11 { 12 int a, b; //两点的下标 13 double len; //边长 14 }side; 15 16 point p[N]; 17 side s[N*N]; 18 int bleg[N]; //存储父节点 19 int pn; //点的数量 20 int sn = 0; //边的数量 21 double ans = 0; //答案 22 23 void Init(); //初始化 24 25 void Read(); //输入点并且计算边 26 27 double Count(int x, int y); //计算边长 28 29 int Find(int x); //查找操作,用于判断是否成环 30 31 void Union(int x, int y); //合并操作 32 33 int Mycompare(const void *a, const void *b); //用于qsort的排序比较函数 34 35 void Link(); //将边连接起来构造并计算最小生成树 36 37 int main() 38 { 39 scanf("%d", &pn); 40 Init(); 41 Read(); 42 qsort(s, sn, sizeof(s[0]), Mycompare); 43 Link(); 44 printf("%.2lf ", ans); //如果输出为%.2f的话则在以上4种编译器中都能通过 45 return 0; 46 } 47 48 void Init() //初始化 49 { 50 int i; 51 for (i=0; i<N; ++i) 52 { 53 bleg[i] = i; 54 } 55 ans = 0; 56 return; 57 } 58 59 void Read() //输入点并且计算边 60 { 61 int i, j; 62 for (i=0; i<pn; ++i) 63 { 64 scanf("%lf %lf", &p[i].x, &p[i].y); 65 for (j=0; j<i; ++j) //开始计算边的信息 66 { 67 s[sn].a = i; 68 s[sn].b = j; 69 s[sn++].len = Count(i, j); 70 } 71 } 72 return; 73 } 74 75 double Count(int x, int y) //计算边长 76 { 77 double lx = (p[x].x - p[y].x) * (p[x].x - p[y].x); 78 double ly = (p[x].y - p[y].y) * (p[x].y - p[y].y); 79 double len = sqrt(lx + ly); 80 return len; 81 } 82 83 int Find(int x) //查找操作,用于判断是否成环 84 { 85 int y = bleg[x]; 86 int z; 87 while (y != bleg[y]) 88 { 89 y = bleg[y]; 90 } 91 while (x != bleg[x]) 92 { 93 z = bleg[x]; 94 bleg[x] = y; 95 x = z; 96 } 97 return y; 98 } 99 100 void Union(int x, int y) //合并操作 101 { 102 int fx = Find(x); 103 int fy = Find(y); 104 bleg[fx] = fy; 105 return; 106 } 107 108 int Mycompare(const void *a, const void *b) //用于qsort的排序比较函数 109 { 110 if ((*(side *)a).len > (*(side *)b).len) 111 { 112 return 1; 113 } 114 return -1; 115 } 116 117 void Link() //将边连接起来构造并计算最小生成树 118 { 119 int i; 120 for (i=0; i<sn; i++) 121 { 122 if (Find(s[i].a) != Find(s[i].b)) 123 { 124 Union(s[i].a, s[i].b); 125 ans += s[i].len; 126 } 127 } 128 return; 129 }