正题
第三题:无线通讯网
这题中的卫星电话,就指的是可以把原图分成S个联通块后,就可以互相联通。
那我们要把原图分成S个联通块,那么我们只需要选中P-S条最短的边(当然是不联通的两个点)。
然后输出最大边最小即可,那么想到了最大边最小,我们就想到了最小生成树,选S-P条边即可。
代码<我是二分的,太菜了>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct node{
double x,y;
}p[510];
int m,n;
double d[510][510];
struct edge{
int x,y;
double c;
}s[250010];
int len=0;
int f[510];
int t[250010];
bool tf[510];
bool cmp(edge x,edge y){
return x.c<y.c;
}
void ins(int x,int y,double c){
len++;
s[len].x=x;s[len].y=y;s[len].c=c;
}
double dis(int x,int y){
double x1=p[x].x,x2=p[y].x,y1=p[x].y,y2=p[y].y;
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int findpa(int x){
if(f[x]!=x) return f[x]=findpa(f[x]);
return f[x];
}
bool check(int x){
for(int i=1;i<=n;i++)
f[i]=i;
memset(tf,false,sizeof(tf));
for(int i=1;i<=x;i++){
int fx=findpa(s[i].x),fy=findpa(s[i].y);
if(fx!=fy) f[fx]=fy;
}
int tot=0;
for(int i=1;i<=n;i++){
int p=findpa(i);
if(tf[p]==false) {
tot++;
tf[p]=true;
}
}
if(tot<=m) return true;
return false;
}
int main(){
scanf("%d %d",&m,&n);
for(int i=1;i<=n;i++){
double x,y;
scanf("%lf %lf",&x,&y);
p[i].x=x;p[i].y=y;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=i-1;j++)
ins(i,j,dis(i,j));
}
sort(s+1,s+1+len,cmp);
int l=1,r=len;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
r=mid-1;
ans=mid;
}
else l=mid+1;
}
printf("%.2lf",s[ans].c);
}