1. 程式人生 > >BZOJ 1821 Group 部落劃分 並查集

BZOJ 1821 Group 部落劃分 並查集

sort begin 分布 好的 target clu lan gin getchar

題目鏈接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1821

題目大意:

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

思路:

按邊排序,從小到大合並,直到恰好連通塊數目為k是的邊就是最大的最小距離。

 1 #include<bits/stdc++.h>
 2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
 3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用於函數,會超時
 4 #define Min(a, b) ((a) < (b) ? (a) : (b))
 5 #define Mem(a) memset(a, 0, sizeof(a))
 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
 7
#define MID(l, r) ((l) + ((r) - (l)) / 2) 8 #define lson ((o)<<1) 9 #define rson ((o)<<1|1) 10 #define Accepted 0 11 #pragma comment(linker, "/STACK:102400000,102400000")//棧外掛 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while (ch<0||ch>9){if (ch==
-) f=-1;ch=getchar();} 17 while (ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} 18 return x*f; 19 } 20 typedef long long ll; 21 const int maxn = 1000 + 10; 22 const int MOD = 1000000007;//const引用更快,宏定義也更快 23 const int INF = 1e9 + 7; 24 const double eps = 1e-6; 25 26 struct node 27 { 28 ll x, y; 29 node(){} 30 node(ll x, ll y):x(x), y(y){} 31 }a[maxn]; 32 struct edge 33 { 34 int u, v; 35 ll w; 36 edge(){} 37 edge(int u, int v, ll w):u(u), v(v), w(w){} 38 bool operator < (const edge& a)const 39 { 40 return w < a.w; 41 } 42 }; 43 vector<edge>e; 44 ll F(int i, int j) 45 { 46 return (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y); 47 } 48 int pa[maxn]; 49 int Find(int x) 50 { 51 return x == pa[x] ? x : pa[x] = Find(pa[x]); 52 } 53 int main() 54 { 55 int n, k; 56 scanf("%d%d", &n, &k); 57 for(int i = 1; i <= n; i++)scanf("%lld%lld", &a[i].x, &a[i].y); 58 for(int i = 1; i <= n; i++) 59 for(int j = i + 1; j <= n; j++) 60 e.push_back(edge(i, j, F(i, j))); 61 sort(e.begin(), e.end()); 62 for(int i = 1; i <= n; i++)pa[i] = i; 63 for(int i = 0; i < e.size(); i++) 64 { 65 if(Find(e[i].u) != Find(e[i].v)) 66 { 67 if(n > k) 68 { 69 n--;//連通塊數目減一 70 pa[Find(e[i].u)] = Find(e[i].v); 71 } 72 else 73 { 74 printf("%.2lf\n", sqrt(1.0 * e[i].w)); 75 break; 76 } 77 } 78 } 79 return Accepted; 80 }

BZOJ 1821 Group 部落劃分 並查集