题目描述
国防部(DND)希望通过无线网络连接几个北部前哨站。
在建立网络时将使用两种不同的通信技术:每个前哨站都有一个无线电收发器,一些前哨站还有一个通信卫星。
任意两个拥有通信卫星的前哨站不论它们的位置如何,都可以通过卫星进行通信。
而如果利用无线电进行通信,则需要两个前哨站的距离不能超过 D 方可进行通信。
而 D 的大小取决于收发器的功率,收发器的功率越大,D 也就越大,但是需要的成本也就越高。
出于采购和维护的考虑,所有的前哨站都采用相同的收发器,也就是说所有前哨站的无线电通信距离 D 都是相同的。
你需要确定在保证任意两个前哨站之间都能进行通信(直接或间接)的情况下,D 的最小值是多少。
输入格式
第一行包含整数 N,表示共有 N 组测试数据。
每组数据的第一行包含两个整数 S 和 P,其中 S 为卫星个数,P 为前哨站个数。
接下来 P 行每行包含两个整数 x 和 y,分别表示一个前哨站的横纵坐标。
输出格式
输出一个实数,表示 D 的最小值,结果保留两位小数。
数据范围
1
≤
S
≤
100
,
1≤S≤100,
1≤S≤100,
S
≤
P
≤
500
,
S≤P≤500,
S≤P≤500,
0
≤
x
,
y
≤
10000
0≤x,y≤10000
0≤x,y≤10000
输入样例:
1
2 4
0 100
0 300
0 600
150 750
输出样例:
212.13
题解
一道最小生成树模板题,我们已经有了
S
S
S个卫星,也就是说,我们可以不消耗代价的将
S
S
S个点连接在树中,也就是连接了
S
−
1
S-1
S−1条边
那么我们最小生成树总共需要连接
P
−
1
P-1
P−1条边,则还需要连接
P
−
S
P-S
P−S条边,所以找出被连接的第
P
−
S
P-S
P−S条边的权值即可
写一个裸的Kruskal就AC了
code
#include<bits/stdc++.h>
using namespace std;
const int N=510;
const int M=N*N;
int T;
int s,p;
double x[N],y[N];
struct node
{
int u,v;
double w;
}edge[M];
bool cmp(node x,node y)
{
return x.w<y.w;
}
int fa[N];
int get(int x)
{
if(x==fa[x]) return x;
else return fa[x]=get(fa[x]);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&s,&p);
for(int i=1;i<=p;i++) fa[i]=i;
for(int i=1;i<=p;i++) scanf("%lf%lf",&x[i],&y[i]);
int tot=0;
for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++)
{
if(i==j) continue;
edge[++tot].u=i;
edge[tot].v=j;
edge[tot].w=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
sort(edge+1,edge+1+tot,cmp);
int t=0;
for(int i=1;i<=tot;i++)
{
int fx=get(edge[i].u),fy=get(edge[i].v);
if(fx==fy) continue;
fa[fx]=fy;
t++;
if(t==p-s)
{
printf("%.2lf\n",edge[i].w);
break;
}
}
}
return 0;
}