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