1. 程式人生 > 實用技巧 >【Luogu P4047】[JSOI2010]部落劃分

【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;
}