链接:P1991
题目描述
国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;
每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。
任意两个配备了一条卫星电话线路的哨所(两边都有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 D,这是受收发器的功率限制。收发器的功率越高,通话距离 D 会更远,但同时价格也会更贵。
收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 D。你的任务是确定收发器必须的最小通话距离 D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。
输入格式
从 wireless.in中输入数据第 1 行,2 个整数 S 和 P,S 表示可安装的卫星电话的哨所数,P 表示边防哨所的数量。接下里 P 行,每行两个整数 x,y 描述一个哨所的平面坐标(x, y),以 km 为单位。
输出格式
输出 wireless.out 中
第 1 行,1 个实数 D,表示无线电收发器的最小传输距离,精确到小数点后两位。
输入输出样例
输入 #1
2 4
0 100
0 300
0 600
150 750
输出 #1
212.13
说明/提示
对于 20% 的数据:P = 2,S = 1
对于另外 20% 的数据:P = 4,S = 2
对于 100% 的数据保证:1 ≤ S ≤ 100,S < P ≤ 500,0 ≤ x,y ≤ 10000。
先把每两点之间的距离用两点之间坐标公式求出存储在一个结构体中
因为有几个点使用卫星不需要考虑距离,我们就要尽量把距离越远代价越高的使用卫星
即贪心思想
按照从小到大距离大小顺序,然后用并查集将前面代价小的合并起来()用无线电,直到加上卫星后可以全部连在一起。
(没错,又是最小生成树克鲁斯卡尔算法改动一下又能ac
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
struct CZP
{
int x,y;
double z;
}a[1000001];
int fa[10001],c[100001][2],n,t,top;
int find(int x)
{
if (x==fa[x])
return x;
else
fa[x]=find(fa[x]);
return fa[x];
} //并查集路径压缩
double js(int x1,int y1,int x2,int y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
} //两点之间坐标公式
int cmp(CZP a,CZP b)
{
return a.z<b.z;
}
int main()
{
scanf("%d%d",&t,&n);
for (int i=1;i<=n;i++)
fa[i]=i;
for (int i=1;i<=n;i++)
scanf("%d%d",&c[i][0],&c[i][1]);
for (int i=1;i<n;i++)
{
for (int j=i+1;j<=n;j++)
{
a[++top].x=i;
a[top].y=j;
a[top].z=js(c[i][0],c[i][1],c[j][0],c[j][1]);
}
} //把每两点之间坐标距离存储起来,表示每两点之间花费的代价
sort(a+1,a+top+1,cmp);
int k=0;
for (int i=1;i<=top;i++)
{
int x1=find(a[i].x),y1=find(a[i].y);
if (x1!=y1)
{
fa[y1]=x1;
k++;
}
if (k==n-t) //如果加上使用卫星的t个点已经可以全部连通了,那么就说明全部连通
{
printf("%.2lf\n",a[i].z);
//由于每一个无线电距离是一样的,只能选当前距离最大的为无线电距离
return 0;
}
}
return 0;
}