zoukankan      html  css  js  c++  java
  • HDOJ-1875-畅通工程再续 解题报告

           一道最小生成树题目。题意为中文描述不多说。比起一般的最小生成树题目来说,本题需要考虑浮点数的比较,另外对边长也有限制(如题目所说:两岛之间的距离不能小于10米也不能大于1000米),也就是说在此情况下不能直接将两小岛连通。


           我的解题思路:首先计算和比较浮点数的大小要尤其注意,其次根据题意,两岛之间的距离不满足题目要求的视做无法直接连通。注意这两点之后用kruskal算法或者prim算法解决就可以了。


           下面是解题代码:kruskal解法

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <math.h>
      4 #define N 105
      5 
      6 typedef struct side     //定义边结构体
      7 {
      8     int a, b;       //两点(岛)的下标
      9     double len;     //边长(距离)
     10 }side;
     11 
     12 typedef struct point    //定义点结构体
     13 {
     14     int x, y;   //坐标
     15 }point;
     16 
     17 point p[N];
     18 side s[N*N];
     19 int bleg[N];    //并查集使用,存储父节点
     20 int pn;     //点的数量
     21 int sn;     //边的数量
     22 int t;      //测试样例数
     23 
     24 void Init();        //初始化
     25 
     26 void Read();        //输入
     27 
     28 double Count(int i, int j);     //计算边长
     29 
     30 void Kruskal();
     31 
     32 int Mycmp(const void *a, const void *b);    //qsort比较函数
     33 
     34 int Find(int x);    //并查集查找
     35 
     36 void Union(int x, int y);   //并查集合并
     37 
     38 int Test();     //检测工程是否畅通
     39 
     40 int main()
     41 {
     42     scanf("%d", &t);
     43     while (t--)
     44     {
     45         Init();
     46         Read();
     47         Kruskal();
     48     }
     49     return 0;
     50 }
     51 
     52 void Init()         //初始化
     53 {
     54     int i;
     55     for (i=0; i<N; ++i)
     56     {
     57         bleg[i] = i;
     58     }
     59     sn = pn = 0;
     60     return;
     61 }
     62 
     63 void Read()         //输入
     64 {
     65     int i, j;
     66     scanf("%d", &pn);
     67     for (i=0; i<pn; ++i)
     68     {
     69         scanf("%d %d", &p[i].x, &p[i].y);
     70         for (j=0; j<i; ++j)     //开始计算新增的边
     71         {
     72             s[sn].a = i;
     73             s[sn].b = j;
     74             s[sn++].len = Count(i, j);
     75         }
     76     }
     77     return;
     78 }
     79 
     80 double Count(int i, int j)      //计算边长
     81 {
     82     double dx = ((double)p[i].x - p[j].x) * (p[i].x - p[j].x);
     83     double dy = ((double)p[i].y - p[j].y) * (p[i].y - p[j].y);
     84     return sqrt(dx + dy);
     85 }
     86 
     87 void Kruskal()
     88 {
     89     int i;
     90     double ans = 0;
     91     qsort(s, sn, sizeof(side), Mycmp);
     92     for (i=0; i<sn; ++i)    //忽略边长小于10的边
     93     {
     94         if (s[i].len >= 10) break;
     95     }
     96     for (; i<sn; ++i)
     97     {
     98         if (s[i].len <= 1000 && Find(s[i].a) != Find(s[i].b))       //要求边长小于等于1000
     99         {
    100             ans += s[i].len;
    101             Union(s[i].a, s[i].b);
    102         }
    103     }
    104     if (Test() == 1)
    105     {
    106         printf("%.1f
    ", 100 * ans);
    107     }
    108     else
    109     {
    110         printf("oh!
    ");
    111     }
    112     return;
    113 }
    114 
    115 int Mycmp(const void *a, const void *b)     //qsort比较函数
    116 {
    117     if ((*(side *)a).len > (*(side *)b).len)
    118     {
    119         return 1;
    120     }
    121     return -1;
    122 }
    123 
    124 int Find(int x)     //并查集查找
    125 {
    126     int y = bleg[x];
    127     int z;
    128     while (y != bleg[y])
    129     {
    130         y = bleg[y];
    131     }
    132     while (x != bleg[x])
    133     {
    134         z = bleg[x];
    135         bleg[x] = y;
    136         x = z;
    137     }
    138     return y;
    139 }
    140 
    141 void Union(int x, int y)        //并查集合并
    142 {
    143     int fx = Find(x);
    144     int fy = Find(y);
    145     bleg[fx] = fy;
    146     return;
    147 }
    148 
    149 int Test()      //检测工程是否畅通
    150 {
    151     int i;
    152     int x = bleg[0];
    153     for (i=1; i<pn; ++i)
    154     {
    155         if (bleg[i] != x)   //出现有两小岛不属于同一个集合时说明工程未畅通
    156         {
    157             return 0;
    158         }
    159     }
    160     return 1;
    161 }
  • 相关阅读:
    Linux下semaphore的使用 进程间互斥的一个好方法
    CURL编程:什么是NonASCII平台,如何取得页面的charset
    C++中的重载(Overload), 覆盖(Override)和隐藏(Hide)
    system调用虽然用了exec,但是fd, signal这些还是会保留父进程的,be careful
    addr2line,可以根据一个地址打印出对应的代码行
    POSIX Threads Programming 阅读笔记(来自劳伦斯利物浦实验室的文章)
    [Gammu]setlocale和bindtextdomain函数的用法
    常用编码
    用PL/SQL画直方图
    窗体的关闭
  • 原文地址:https://www.cnblogs.com/JZQT/p/3802442.html
Copyright © 2011-2022 走看看