1. 程式人生 > 其它 >洛谷P4047 [JSOI2010]部落劃分 題解

洛谷P4047 [JSOI2010]部落劃分 題解

技術標籤:演算法機器學習大資料spark聚類演算法

[JSOI2010]部落劃分 - 洛谷

description:

給定平面直角座標系上的

n 個點,請將這 n 個點合併成 k 個集合,使得最終距離最小的集合距離最大。

(兩個集合間的距離指的是其中最近元素的距離。

solution:

我們觀察到資料範圍較小,直接暴力兩兩點之間建邊。

然後我們相當於把一些點合併到另一些點當中,合併

n-k 條邊即可。

跑最小生成樹。

code:

#include<cstdio>
#include<cmath>
#include<algorithm>
using
namespace std; struct ben { int x,y; double val; }a[1000005]; int cmp(const ben &a,const ben &b) { return a.val<b.val; } int fa[1005]; int find(int x) { if(fa[x]!=x)fa[x]=find(fa[x]); return fa[x]; } double x[1005],y[1005]; int main() { int n,k; scanf("%d%d",&n,&k); for(int
i=1;i<=n;i++) { fa[i]=i; scanf("%lf%lf",&x[i],&y[i]); } int cnt=0; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { a[++cnt].x=i; a[cnt].y=j; a[cnt].val=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } } sort(a+1,a+cnt+1,cmp); int sum=0; for
(int i=1;i<=cnt;i++) { int x=find(a[i].x); int y=find(a[i].y); if(x!=y) { fa[y]=x; sum++; } if(sum==n-k+1) { printf("%.2lf\n",a[i].val); break; } } return 0; }