1. 程式人生 > >[Bzoj1821][JSOI2010]Group 部落劃分 Group(並查集)(二分答案)

[Bzoj1821][JSOI2010]Group 部落劃分 Group(並查集)(二分答案)

ble 輸出 content 有意 表示 com 自己 clu 我們

1821: [JSOI2010]Group 部落劃分 Group


Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 2949 Solved: 1392
[Submit][Status][Discuss]

Description


聰聰研究發現,荒島野人總是過著群居的生活,但是,並不是整個荒島上的所有野人都屬於同一個部落,野人們總是拉幫結派形成屬於自己的部落,不同的部落之間則經常發生爭鬥。只是,這一切都成為謎團了——聰聰根本就不知道部落究竟是如何分布的。 不過好消息是,聰聰得到了一份荒島的地圖。地圖上標註了N個野人居住的地點(可以看作是平面上的坐標)。我們知道,同一個部落的野人總是生活在附近。我們把兩個部落的距離,定義為部落中距離最近的那兩個居住點的距離。聰聰還獲得了一個有意義的信息——這些野人總共被分為了K個部落!這真是個好消息。聰聰希望從這些信息裏挖掘出所有部落的詳細信息。他正在嘗試這樣一種算法: 對於任意一種部落劃分的方法,都能夠求出兩個部落之間的距離,聰聰希望求出一種部落劃分的方法,使靠得最近的兩個部落盡可能遠離。 例如,下面的左圖表示了一個好的劃分,而右圖則不是。請你編程幫助聰聰解決這個難題。 技術分享

Input


第一行包含兩個整數N和K(1< = N < = 1000,1< K < = N),分別代表了野人居住點的數量和部落的數量。 接下來N行,每行包含兩個正整數x,y,描述了一個居住點的坐標(0 < =x, y < =10000)

Output


輸出一行,為最優劃分時,最近的兩個部落的距離,精確到小數點後兩位。

Sample Input


4 2
0 0
0 1
1 1
1 0    



Sample Output


1.00

分析:


我看到的野人怎麽和這個野人不一樣呢,他們團結一致來欺負我,根本不會分部落(forest)。

二分距離,小於當前距離的點對加並查集,最後統計聯通塊個數跟k的關系。還是比較容易的

AC代碼:

# include <iostream>
# include <cstdio>
# include <cmath>
# include <cstring>
using namespace std;
const int N = 1e3 + 12;
const double res = 1e-6;
int pre[N],n,k;
double x[N],y[N]; int find(int x){ if(x != pre[x])return pre[x] = find(pre[x]); return x; } double dis(int i,int j){ return sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])); } bool check(double dist){ int cnt = n; for(int i = 1;i <= n;i++)pre[i] = i; for(int i = 1;i <= n;i++){ for(int j = i + 1;j <= n;j++){ if(dis(i,j) < dist){ int a = find(i),b = find(j); if(a != b){ cnt--; pre[b] = a; } } } } return cnt >= k; } int main(){ scanf("%d %d",&n,&k); for(int i = 1;i <= n;i++){ scanf("%lf %lf",&x[i],&y[i]); } double l = 0,r = 15000,mid,ans; while(r - l > res){ mid = (l + r) / 2; if(check(mid)){ l = mid + res,ans = mid; }else r = mid - res; } printf("%.2lf",ans); }


[Bzoj1821][JSOI2010]Group 部落劃分 Group(並查集)(二分答案)