【BZOJ】1821: [JSOI2010]Group 部落划分 Group(最小生成树+贪心)
时间:2014-08-07 00:21:47
收藏:0
阅读:267
http://www.lydsy.com:808/JudgeOnline/problem.php?id=1821

这题裸题。
本题要求最短距离最长,很明显,我们排序。
这里存在贪心,即我们把边权最小的全分给n个部落的内部,然后剩下的边最小的就是答案。
将边权较小的边分给k个部落,用并查集生成最小树,使得内部的边总是小于连到外部的边。然后分剩下k个点即可,剩下的k个点的那条边一定是部落之间最小的且最长的边。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define read(a) a=getnum()
#define print(a) printf("%d", a)
inline int getnum() { int ret=0; char c; int k=1; for(c=getchar(); c<‘0‘ || c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘ && c<=‘9‘; c=getchar()) ret=ret*10+c-‘0‘; return k*ret; }
const int N=1005;
int x[N], y[N];
struct edge {
int u, v, w;
bool operator < (const edge &a) const { return w<a.w; }
}e[N*N];
int cnt;
int f[N];
int ifind(const int &x) { return x==f[x]?x:f[x]=ifind(f[x]); }
int main() {
int n, m;
read(n); read(m);
for1(i, 1, n) read(x[i]), read(y[i]);
for1(i, 1, n) f[i]=i;
for1(i, 1, n) for1(j, 1, n) if(i!=j) e[cnt].u=i, e[cnt].v=j, e[cnt++].w=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
sort(e, e+cnt);
int fu, fv;
for2(i, 0, cnt) {
fu=ifind(e[i].u); fv=ifind(e[i].v);
if(fu!=fv) {
if(n>m) --n, f[fu]=fv;
else {
printf("%.2lf\n", sqrt(e[i].w));
break;
}
}
}
return 0;
}
【BZOJ】1821: [JSOI2010]Group 部落划分 Group(最小生成树+贪心),布布扣,bubuko.com
评论(0)