一道最小生成树题目。题意为中文描述不多说。比起一般的最小生成树题目来说,本题需要考虑浮点数的比较,另外对边长也有限制(如题目所说:两岛之间的距离不能小于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 }