题解 | #信号覆盖#

信号覆盖

https://www.nowcoder.com/practice/35175cee9e634b92b35b634244d81feb

解题思路:二分+并查集

时间复杂度:O(n^2 * log(x^2+y^2))

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e3+100;

int n,k;
int fa[MAXN];  //并查集,记录当前节点的父节点,初始化fa[i] = i;
int d[MAXN][MAXN]; //记录距离
pair<int,int>pos[MAXN]; //记录坐标
int num[MAXN]; // 记录每个集合的数量,初始化均为1

int get_fa(int x){ //获得集合的root
    if(fa[x]==x)return x;
    return fa[x] = get_fa(fa[x]);
}
int get_num(int x){ //获得数量
    x = get_fa(x);
    return num[x];
}
void merge(int x, int y){ //合并两个集合
    x = get_fa(x);
    y = get_fa(y);
    if(x==y)return;
    fa[x] = y;
    num[y]+=num[x];
}
int solve(int ma){ //二分找答案
    int r = ma;
    int l = 0;
    while(l<r){
        int max_num=0;
        for(int i=1;i<=n;++i){  //初始化fa数组和num数组
            fa[i] = i;
            num[i] = 1;
        }
        int mid = (l+r)/2;  
        for(int i=1;i<=n;++i){ //把所有能通信的merge一块儿
            for(int j=1;j<i;++j){
                if(d[i][j]<=mid)merge(i,j); //merge中更新num和fa
            }
        }
        for(int i=1;i<=n;++i){// 查找最大的集合
            max_num = max(max_num, get_num(i));
        }
        if(max_num>=k)r=mid;//如果最大的集合大于k,说明还可以缩小
        else l=mid+1; //小于k,则不能再缩小了
    }
    return l;
}
int main() {
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&pos[i].first, &pos[i].second);
    int ma = 0;
    for(int i=1;i<=n;++i){ //更新距离
        for(int j=1;j<=n;++j){
            d[i][j] = (pos[i].first-pos[j].first)*(pos[i].first-pos[j].first);
            d[i][j]+=(pos[i].second-pos[j].second)*(pos[i].second-pos[j].second);
            ma = max(ma,d[i][j]); //记录最大值,最大值的时候所有都互相连接
        }
    }
    printf("%d\n",solve(ma));
    
}

全部评论

相关推荐

04-25 10:45
东南大学 Java
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务