题目描述
国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。任意两个配备了一条卫星电话线路的哨所(两边都有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 D,这是受收发器的功率限制。收发器的功率越高,通话距离 D 会更远,但同时价格也会更贵。收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 D。你的任务是确定收发器必须的最小通话距离 D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。
输入格式
第一行,2 个整数 S 和 P,S 表示可安装的卫星电话的哨所数,P 表示边防哨所的数量。
接下里 P 行,每行两个整数 x,y 描述一个哨所的平面坐标 (x,y),以 km 为单位。
输出格式
第一行,1个实数 D,表示无线电收发器的最小传输距离,精确到小数点后两位。
输入输出样例
2 4
0 100
0 300
0 600
150 750
输出
212.13
总结如下:
这是一个基于通信技术和设备选择的最小通话距离问题。可以使用图论中的最小生成树算法来解决这个问题。
首先,我们可以将每个边防哨所看作图中的节点,通信技术和设备之间的连接看作边。我们需要找到一个最小通话距离 D,使得图中的所有节点都能够通过边连接起来。
然后,我们可以使用最小生成树算法,例如Prim算法或Kruskal算法,来找到一个最小生成树。最小生成树是一个包含所有节点的子图,其中任意两个节点之间的路径长度之和最小。
最后,我们可以根据最小生成树中的最长边来确定收发器必须的最小通话距离 D。因为最长边表示最远距离的通信连接,其他边的长度都不会超过这个最长边的长度。
代码如下:
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int n, m,cnt=0,sum=0;
double ans = 0;
int f[1000001];
struct node {
int x;
int y;
}a[1000001];
struct node1 {
int u;
int v;
double w;
}b[1000001];
bool cmp(struct node1 a, struct node1 b) {
return a.w < b.w;
}
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
double jisuan(int x, int y) {
return (double)sqrt((double)(a[x].x - a[y].x) * (a[x].x - a[y].x) + (double)(a[x].y - a[y].y) * (a[x].y - a[y].y));
}
void add(int x, int y, double z) {
b[++cnt].u = x;
b[cnt].v = y;
b[cnt].w = z;
}
void krusal() {
for (int i = 1; i <= cnt; i++) {
int fa = find(b[i].u);
int fb = find(b[i].v);
if (fa == fb)continue;
f[fa] = fb;
sum++;
ans = b[i].w;
if (sum == m - n)return;
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> a[i].x >> a[i].y;
}
for (int i = 1; i <= m; i++) f[i] = i;
for (int i = 1; i <= m; i++) {
for (int j = i + 1; j <= m; j++) {
double z = jisuan(i, j);
add(i, j, z);
}
}
sort(b + 1, b + 1 + cnt, cmp);
krusal();
printf("%.2lf", ans);
return 0;
}