题解 | #信号覆盖#
信号覆盖
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));
}
查看7道真题和解析