HDOJ-1875-畅通工程再续 解题报告
2014-06-02 21:43
274 查看
一道最小生成树题目。题意为中文描述不多说。比起一般的最小生成树题目来说,本题需要考虑浮点数的比较,另外对边长也有限制(如题目所说:两岛之间的距离不能小于10米也不能大于1000米),也就是说在此情况下不能直接将两小岛连通。
我的解题思路:首先计算和比较浮点数的大小要尤其注意,其次根据题意,两岛之间的距离不满足题目要求的视做无法直接连通。注意这两点之后用kruskal算法或者prim算法解决就可以了。
下面是解题代码:kruskal解法
我的解题思路:首先计算和比较浮点数的大小要尤其注意,其次根据题意,两岛之间的距离不满足题目要求的视做无法直接连通。注意这两点之后用kruskal算法或者prim算法解决就可以了。
下面是解题代码:kruskal解法
#include <stdio.h> #include <stdlib.h> #include <math.h> #define N 105 typedef struct side //定义边结构体 { int a, b; //两点(岛)的下标 double len; //边长(距离) }side; typedef struct point //定义点结构体 { int x, y; //坐标 }point; point p ; side s[N*N]; int bleg ; //并查集使用,存储父节点 int pn; //点的数量 int sn; //边的数量 int t; //测试样例数 void Init(); //初始化 void Read(); //输入 double Count(int i, int j); //计算边长 void Kruskal(); int Mycmp(const void *a, const void *b); //qsort比较函数 int Find(int x); //并查集查找 void Union(int x, int y); //并查集合并 int Test(); //检测工程是否畅通 int main() { scanf("%d", &t); while (t--) { Init(); Read(); Kruskal(); } return 0; } void Init() //初始化 { int i; for (i=0; i<N; ++i) { bleg[i] = i; } sn = pn = 0; return; } void Read() //输入 { int i, j; scanf("%d", &pn); for (i=0; i<pn; ++i) { scanf("%d %d", &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 i, int j) //计算边长 { double dx = ((double)p[i].x - p[j].x) * (p[i].x - p[j].x); double dy = ((double)p[i].y - p[j].y) * (p[i].y - p[j].y); return sqrt(dx + dy); } void Kruskal() { int i; double ans = 0; qsort(s, sn, sizeof(side), Mycmp); for (i=0; i<sn; ++i) //忽略边长小于10的边 { if (s[i].len >= 10) break; } for (; i<sn; ++i) { if (s[i].len <= 1000 && Find(s[i].a) != Find(s[i].b)) //要求边长小于等于1000 { ans += s[i].len; Union(s[i].a, s[i].b); } } if (Test() == 1) { printf("%.1f\n", 100 * ans); } else { printf("oh!\n"); } return; } int Mycmp(const void *a, const void *b) //qsort比较函数 { if ((*(side *)a).len > (*(side *)b).len) { return 1; } return -1; } 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 Test() //检测工程是否畅通 { int i; int x = bleg[0]; for (i=1; i<pn; ++i) { if (bleg[i] != x) //出现有两小岛不属于同一个集合时说明工程未畅通 { return 0; } } return 1; }
相关文章推荐
- 最小生成树——HDOJ 1863 畅通工程 解题报告
- hdu 1875 畅通工程再续 解题报告
- 最小生成树——HDOJ 1233 还是畅通工程 解题报告
- HDOJ 1232 畅通工程解题报告
- 【解题报告】 HDU 1875 畅通工程再续 Kruskal最小生成树 一点关于浮点型在计算机中储存的分析
- HDOJ--1875--畅通工程再续
- HDOJ 畅通工程再续 1875
- HDOJ1875畅通工程--克鲁斯卡尔算法与查并集探骊
- hdoj 1875 畅通工程再续 【最小生成树】
- HDU1879 继续畅通工程 解题报告--prim
- hdu 1232 畅通工程 解题报告
- HDU 畅通工程系列题目解题报告 (HDU1232+HDU1233+HDU1863+HDU1874+HDU1875+HDU1879)
- 【解题报告】HDU 1874 畅通工程续 -- Dijkstra算法详解 单源点最短路问题
- HDoj-1875-畅通工程再续-prim算法
- hdoj 1875 畅通工程再续 【最小生成树】
- hdoj 1875 畅通工程再续(最小生成树)
- 畅通工程之并查集解题报告
- hdoj 1875 畅通工程再续 【最小生成树】
- HDU 畅通工程系列题目解题报告 (HDU1232+HDU1233+HDU1863+HDU1874+HDU1875+HDU1879)
- hdu 1863 畅通工程 解题报告