[二分+并查集] BZOJ1821 : [JSOI2010]Group 部落划分 Group

本文介绍了一种利用二分查找结合并查集解决部落划分问题的方法。通过设定两个点之间的最大允许距离来确定最少部落数量。采用C++实现算法流程,包括读取输入数据、二分查找合适距离及使用并查集进行节点合并。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分距离最小值。两个点的距离小于这个值,就一定要在同一个部落中。并查集判断一下就行了。

#include<cstdio>
#include<algorithm>
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long LL;
const int maxn=1005;
int n,m,a[maxn],b[maxn],fa[maxn]; 
double mid;
int getfa(int x){ return fa[x]==x?x:fa[x]=getfa(fa[x]); }
void merge(int x,int y){ x=getfa(x); y=getfa(y); if(x!=y) fa[x]=y; }
bool check(){
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=n;i++)
     for(int j=i+1;j<=n;j++) if(sqr(a[i]-a[j])+sqr(b[i]-b[j])<mid*mid) merge(i,j); 
    int res=0;
    for(int i=1;i<=n;i++) if(getfa(i)==i) res++;
    return res>=m;
}
int main(){
    freopen("bzoj1821.in","r",stdin);
    freopen("bzoj1821.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
    double L=0.01,R=1e12;
    while(R-L>=0.001){
        mid=(L+R)/2;
        if(check()) L=mid; else R=mid;
    }
    printf("%.2lf\n",L);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值