BZOJ 1821 Group 部落划分 并查集

题目链接:

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 }

 

posted @ 2018-09-24 19:49  _努力努力再努力x  阅读(132)  评论(0编辑  收藏  举报