【Luogu P4047】[JSOI2010]部落划分
题目大意:
给 \(n\) 个点分组,使得最近的两组最远。
正文:
由 最近的两组最远
想到二分答案,分组
也可以联想到并查集。用二分答案,很明显二分的是“最近的两组”的距离。而我们可以通过枚举每个点的距离比较当前二分的最近两组距离,如果小于,说明两点皆为同一组内。最后可以通过枚举出的组数比较题目限制的组数调整二分的范围。
代码:
bool check(double x)
{
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if((a[i].x - a[j].x - 0.0) * (a[i].x - a[j].x - 0.0) +
(a[i].y - a[j].y - 0.0) * (a[i].y - a[j].y - 0.0) < x)
fa[find_(i)] = find_(j);
int cnt = 0;
for (int i = 1; i <= n; i++)
if(fa[i] == i) cnt++;
if(cnt < k) return 0;
return 1;
}
int main()
{
scanf ("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].x, &a[i].y),
maxx = max(a[i].x, maxx),
maxy = max(a[i].y, maxy);
double l = 0.0, r = maxx * maxx + maxy * maxy, mid;
while(1e-4 < r-l) //1e-4是精度问题
{
mid = (l + r) / 2.0;
if(check(mid))
l = mid;
else
r = mid;
}
printf("%.2lf", sqrt(l)); //最后才取根号是精度问题
return 0;
}