bzoj1821[JSOI2010]Group 部落划分 Group

bzoj1821[JSOI2010]Group 部落划分 Group

题意:

n个野人,分为k个部落,两个部落之间距离定义为两个部落最近两个野人的距离,要求划分时最近的部落最远。求这种划分下部落间最近距离。n,k≤1000,野人坐标≤10000是整数。

题解:

每次将两个部落连接,则这两个部落之间的距离则消失,因此我们应尽力让那些比较短的边消失,所以先O(n2)弄出野人间两两的边,将它们按距离从小到大排序,然后用类似Kruscal的方法(其实就是Kruscal)连边,最后连的边的下一条可连的边的长度就是所求。注意最后的退出条件是cnt==n-k+1。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define maxn 1010
 7 using namespace std;
 8 
 9 struct e{int f,t,dis;}; e es[maxn*maxn/2]; int ess;
10 bool cmp(e a,e b){return a.dis<b.dis;}
11 int x[maxn],y[maxn],fa[maxn],n,k;
12 inline int read(){
13     char ch=getchar(); int f=1,x=0;
14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
15     return f*x;
16 }
17 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
18 int main(){
19     n=read(); k=read(); inc(i,1,n)x[i]=read(),y[i]=read(); ess=0;
20     inc(i,1,n)inc(j,i+1,n)es[++ess]=(e){i,j,(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])};
21     sort(es+1,es+ess+1,cmp); int cnt=0; inc(i,1,n)fa[i]=i;
22     inc(i,1,ess){
23         int x=find(es[i].f),y=find(es[i].t); if(x==y)continue; fa[x]=y; cnt++;
24         if(cnt==n-k+1){printf("%.2lf",sqrt(es[i].dis)); break;}
25     }
26     return 0;
27 }

 

20160610

posted @ 2016-08-16 23:04  YuanZiming  阅读(345)  评论(0编辑  收藏  举报