zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    机器学习之sigmoid函数
    linux时间校对
    Lumen5.7快速实现Captcha图片验证码功能
    莫烦python教程地址
    获得用户的真实ip HTTP_X_FORWARDED_FOR
    grep日志去重
    asio的网络通讯代码练手
    my simplest kv db
    c++11 线程池学习笔记 (二) 线程池
    c++11 线程池学习笔记 (一) 任务队列
  • 原文地址:https://www.cnblogs.com/JZQT/p/3802450.html
Copyright © 2011-2022 走看看