洛谷-1991 无线通讯网

题目描述
国防部计划用无线网络连接若干个边防哨所。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。

解释:首先枚举每个点,计算他们的距离作为一条边,再从小到大排序呢。我们对边进行二分答案,同时利用并查集维护好联通关系,1-mid的每个团贡献一个卫星电话,mid+1 - t每个点贡献1个卫星电话。最后和s比较就可以二分了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 505
using namespace std;
struct node{
    double x,y;
};
node s[N];
int father[N*N]={0};
int H[N*N]={0};
int n=0,m=0;
struct edge{
    int a,b;
    double c;
};
edge E[N*N];
int t=0;
void init(){
    for(int i=0;i<N*N;i++) father[i]=i,H[i]=0;
}
int find(int x){
    if(father[x]==x) return x;
    return father[x]=find(father[x]);
}
void merge(int x,int y){
    x=find(x);y=find(y);
    father[x]=y;
}
bool cmp(edge &a,edge &b){
    return a.c<b.c;
}
bool same(int x,int y){
    return find(x)==find(y);
}
bool ok(int x){
    init();
    int ret=0;
    for(int i=1;i<=x;i++){
        if(!same(E[i].a,E[i].b)){
            H[E[i].a]=H[E[i].b]=1;
            merge(E[i].a,E[i].b);
        }
    }
    for(int i=1;i<=n;i++){
        if(!H[i]) ret++;
        if(find(i)!=i&&H[find(i)]==1) ret++;
        H[find(i)]=2;
    }
    return ret<=m;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>m>>n;
    for(int i=1;i<=n;i++) cin>>s[i].x>>s[i].y;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            E[++t].a=i,E[t].b=j;
            E[t].c=(s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y);
        }
    }
    sort(E+1,E+1+t,cmp);
    int l=0,r=t;
    int mid=0;
    while(l<r){
        mid=(l+r)/2;
        if(ok(mid)) r=mid;
        else l=mid+1;
    }
    printf("%.2f\n",sqrt(E[l].c));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mkopvec/article/details/92617243
今日推荐