首页 > 代码库 > BZOJ 1821 JSOI2010 部落划分 Group Kruskal
BZOJ 1821 JSOI2010 部落划分 Group Kruskal
题目大意:给定平面上的n个点,要求将这n个点划分为k个集合,使划分后任意两个集合中最近两点的距离的最大值最小,输出这个最小值
考虑这n个点之间所有的连边 我们要让长边保留 就尽量选取短边链接
于是就是求加入n-k条边的最小生成森林 由于输出下一个最小值 因此Kruskal加入第n-k+1条边时输出边权即可
#include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define M 1100 using namespace std; struct point{ int x,y; void Read() { scanf("%d%d",&x,&y); } }points[M]; struct edge{ int x,y; double dis; edge() {} edge(int _,int __,double ___): x(_),y(__),dis(___) {} bool operator < (const edge &e) const { return dis < e.dis; } }edges[1001001]; int n,m,k; double Distance(const point &p1,const point &p2) { return sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) ); } namespace Union_Find_Set{ int fa[M]; inline void Union(int x,int y) { fa[x]=y; } int Find(int x) { if(!fa[x]||fa[x]==x) return fa[x]=x; return fa[x]=Find(fa[x]); } } double Kruskal(int temp) { using namespace Union_Find_Set; int i; sort(edges+1,edges+m+1); for(i=1;i<=m;i++) { int x=Find(edges[i].x); int y=Find(edges[i].y); if(x==y) continue; Union(x,y); if(!--temp) return edges[i].dis; } return 0; } int main() { int i,j; cin>>n>>k; for(i=1;i<=n;i++) points[i].Read(); for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j) edges[++m]=edge(i,j,Distance(points[i],points[j]) ); cout<<fixed<<setprecision(2)<<Kruskal(n-k+1)<<endl; }
BZOJ 1821 JSOI2010 部落划分 Group Kruskal
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。