POJ-2560-Freckles 解题报告

       一个普通的最小生成树问题,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 }
原文地址:https://www.cnblogs.com/JZQT/p/3802450.html