题目链接:无线通讯网 - 洛谷
题目描述
国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;
每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。
任意两个配备了一条卫星电话线路的哨所(两边都ᤕ有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 DD,这是受收发器的功率限制。收发器的功率越高,通话距离 DD 会更远,但同时价格也会更贵。
收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 DD。你的任务是确定收发器必须的最小通话距离 DD,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。
输入格式
从 wireless.in 中输入数据第 1 行,2 个整数 SS 和 PP,SS 表示可安装的卫星电话的哨所数,PP 表示边防哨所的数量。接下里 PP 行,每行两个整数 x,yx,y 描述一个哨所的平面坐标 (x,y)(x,y),以 km 为单位。
输出格式
输出 wireless.out 中
第 1 行,1 个实数 DD,表示无线电收发器的最小传输距离,精确到小数点后两位。
输入输出样例
输入 #1
2 4
0 100
0 300
0 600
150 750输出 #1
212.13
说明/提示
对于 20%20% 的数据:P=2,S=1P=2,S=1
对于另外 20%20% 的数据:P=4,S=2P=4,S=2
对于 100%100% 的数据保证:1≤S≤1001≤S≤100,S<P≤500S<P≤500,0≤x,y≤100000≤x,y≤10000。
算法:最小生成树
思路:
与道路建设那个题类似,就是在那个的代码基础上加了一个排序
先不管是否装电话,
将所有哨所用无向图最小生成树连接起来,
将无向图中所有边(dist数组)从大到小排序
dist[s]即是最后答案
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#define size 10001
double dist[size];//起点到其余各顶点的最短路径长度,初始化为无穷大
bool book[size];//用来标记顶点是否已经并入最短路径,初始化为false表示没有被纳入最短路径
int s, p;//分别表示点的个数,哨所的个数
double all; //all存树路径之和
double map[size][size];//map[i][k]表示从i到k的距离
void init() { //算法初始化
memset(book, 0, sizeof(book));
memset(dist, 0x7f, sizeof(dist));
all = 0; //路径之和清0
book[1] = true; //1为默认源点,源点进入最小生成树
}
void run_prim() {
for (int h = 1; h < p; h++) { //最小生成树中共进入n个顶点,当前生成树中顶点个数为h
int k = 0;
for (int i = 1; i <= p; i++) { //从没有进入树的点中找到离树的任意一个顶点最近的一个点
if (!book[i] && dist[i] < dist[k]) {
k = i;
}
}
all += dist[k];
book[k] = true; //标记该点已经进入最短生成树
for (int i = 1; i <= p; i ++) { //扫描k点所有的边,再以k点为中转点,更新生成树到每一个非树顶点的距离
if (!book[i] && dist[i] > map[i][k] ) {
dist[i] = map[i][k];
}
}
}
}
double cal_dist(int x1, int y1, int x2, int y2) {
return sqrt((double)(x1 - x2) * (x1 - x2) + (double)(y1 - y2) * (y1 - y2));
}
int xy[size][2];//存坐标点坐标
void InsertSort(double* a, int n) {
for (int i = 0; i < n - 1; i++) {
int end = i;
double tmp = a[end + 1];
while (end >= 0) {
if (tmp > a[end]) {
a[end + 1] = a[end];
end--;
} else {
break;
}
}
a[end + 1] = tmp;
}
}
int main() {
scanf("%d %d", &s, &p );
init();//输入n,m,s之后再初始化
for (int i = 1; i <= p; i++) { //输入坐标
scanf("%d %d", &xy[i][0], &xy[i][1]);
}
for (int i = 1; i <= p; i++) {
for (int k = 1; k <= p; k++) {
double tt = cal_dist(xy[i][0], xy[i][1], xy[k][0], xy[k][1]);
map[i][k] = tt;
map[k][i] = tt;
}
}
for (int i = 1; i <= p; i++) {
dist[i] = map[1][i];
}
run_prim();
dist[0] = 0;
InsertSort(dist, p + 1);//插入排序
/*
for(int i=0;i<=p;i++){
printf("%.2lf\n",dist[i]);
}
*/
printf("%.2lf", dist[s - 1]);
}