题目链接请戳 这里
解题思路
最小生成树。用Kruskal得到最小生成树。
再用贪心,最长的那些边连电缆,剩余的用电报,
这样就很容易想到半径是多少。
代码
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #define N 510 using namespace std; struct point { int x, y; }p[N]; struct edge { int u, v; double w; }e[N*N]; int set[N]; int d[N*N]; int n, m, en; int cmp(const int i, const int j) { return e[i].w < e[j].w; } double path(int i, int j) { return sqrt(pow(p[i].x - p[j].x, 2) + pow(p[i].y - p[j].y, 2)); } void make_set() { for(int i = 1; i <= n; i++) set[i] = i; } int find(int x) { return x == set[x] ? x : set[x] = find(set[x]); } double Kruskal(int s) { int t = 0; for(int i = 0; i < en; i++) d[i] = i; make_set(); sort(d, d + en, cmp); for(int i = 0; i < en; i++) { int c = d[i]; int pa = find(e[c].u); int pb = find(e[c].v); if(pa != pb) { t++; set[pa] = pb; if(t == s) return e[c].w; } } } int main() { int tests; scanf("%d", &tests); while(tests--) { scanf("%d%d", &m, &n); for(int i = 1; i <= n; i++) { scanf("%d%d", &p[i].x, &p[i].y); } en = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) if(i != j) { e[en].u = i; e[en].v = j; e[en].w = path(i, j); en++; } } double ans = Kruskal(n - m); printf("%.2lf\n", ans); } return 0; }