模拟赛 无线通讯网

【题目描述】

     国防部计划用无线网络连接若干个边防哨所。2种不同的通讯技术用来搭建无线网络;每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。

任意两个配备了一条卫星电话线路的哨所(两边都拥有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过D,这是受收发器的功率限制。收发器的功率越高,通话距离D会更远,但同时价格也会更贵。

收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个D。

你的任务是确定收发器必须的最小通话距离D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。

【输入格式】 wireless.in

第1行:2个整数S(1<=S<=100)和P(S<P<=500),S表示可安装的卫星电话的哨所数,P表示边防哨所的数量。

     接下里P行,每行描述一个哨所的平面坐标(x,y),以km为单位,整数,0<=x,y<=10000。

【输出格式】 wireless.out

第1行:1个实数D,表示无线电收发器的最小传输距离。精确到小数点后两位。

【样例输入】

 2 4

 0 100

 0 300

 0 600

 150 750

【样例输出】

212.13

数据范围

对于20%的数据  P=2,S=1

对于另外20%的数据  P=4,S=2

对于100%的数据 1<=S<=100,S<P<=500 

题解

并查集+二分。
二分出当前的最小传输距离d,将边重置,用并查集看看有多少个联通块,若联通块数量<=s 则当前的d比较优。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n,s,zz;
struct dian{int x,y;} d[502];
struct bian{int x,y;double v;} e[260002];
int fa[502];
double ans=1e10;
void init()
{
	scanf("%d%d",&s,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&d[i].x,&d[i].y);
	for(int i=1;i<=n;i++)
	for(int j=i+1;j<=n;j++)
	   {zz++; e[zz].x=i; e[zz].y=j;
	    e[zz].v=sqrt((d[i].x-d[j].x)*(d[i].x-d[j].x)+(d[i].y-d[j].y)*(d[i].y-d[j].y));
	   }
}
bool kp(const bian &i,const bian &j)
{return i.v>j.v;}
int find(int x)
{
	if(fa[x]!=x) fa[x]=find(fa[x]);
	return fa[x];
}
bool work(int w)
{
	int ct=n;
	for(int i=1;i<=zz;i++)
	   {if(e[i].v<=e[w].v)
	       {int r1=find(e[i].x),r2=find(e[i].y);
		    if(r1!=r2) {fa[r1]=r2; ct--;}
		   }
	   }
	//printf("%d %d\n",w,ct);
	if(ct<=s) {ans=min(ans,e[w].v); return true;}
	else return false;
}
void doit()
{
	sort(e+1,e+zz+1,kp);
	/*for(int i=1;i<=zz;i++) printf("%d %d %.2lf\n",e[i].x,e[i].y,e[i].v);
	system("pause");*/
	int l=1,r=zz;
	while(l<=r)
	   {for(int i=1;i<=n;i++) fa[i]=i;
	    int mid=(l+r)>>1;
	    if(work(mid)) l=mid+1;
	    else r=mid-1;
	   }
}
int main()
{
	freopen("wireless.in","r",stdin);
	freopen("wireless.out","w",stdout);
	init();
	doit();
	printf("%.2lf\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值