[JSOI2010]GROUP 部落划分 GROUP 把n个点分成k个集, 集合间最小距离最大 最小生成树变形

题目

GROUP 部落划分 GROUP(https://ac.nowcoder.com/acm/problem/20181)

题目描述

聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗。只是,这一切都成为谜团了——聪聪根本就不知道部落究竟是如何分布的。 不过好消息是,聪聪得到了一份荒岛的地图。地图上标注了N个野人居住的地点(可以看作是平面上的坐标)。
我们知道,同一个部落的野人总是生活在附近。我们把两个部落的距离,定义为部落中距离最近的那两个居住点的距离。聪聪还获得了一个有意义的信息——这些野人总共被分为了K个部落!这真是个好消息。聪聪希望从这些信息里挖掘出所有部落的详细信息。
他正在尝试这样一种算法: 对于任意一种部落划分的方法,都能够求出两个部落之间的距离,聪聪希望求出一种部落划分的方法,使靠得最近的两个部落尽可能远离。
例如,下面的左图表示了一个好的划分,而右图则不是。请你编程帮助聪聪解决这个难题。

输入描述:

第一行包含两个整数N和K(1 ≤ N ≤ 1000,1 < K ≤ N),分别代表了野人居住点的数量和部落的数量。
接下来N行,每行包含两个正整数x,y,描述了一个居住点的坐标(0 ≤ x, y ≤ 10000)
输出描述:
输出一行,为最优划分时,最近的两个部落的距离,精确到小数点后两位。

输入

4 2
0 0
0 1
1 1
1 0

输出

1.00

思路

题目意思是把n个点划分成k个集合。使得集合之间的最小距离最大。
点两两之间都有边。
我们考虑最后一定有k个连通块。并且希望优先用短边来连接得到这k个连通块。
那么考虑最小生成树的过程。每次连接一条边,就会减少1个连通块,那么现在我们只要
连接n-k条边。就得到了一个k连通块的图。而且优先选择的短边。那么第n-k+1条可连接的边就是答案。

#include <bits/stdc++.h>
#define LL long long
#define F first
#define S second
#define debug(x) cerr << "Line(" << __LINE__ << ") -> " << #x << " is " << x << endl
using namespace std;

struct Edge {
    int f, to;
    double w;
    int nxt;
} E[2000005];
int head[2000005], cut=0;

void Addedge(int x, int y, double w) {
    E[++cut]= {x, y, w, head[x]};
    head[x]=cut;
}

int x[1005], y[1005];
double dis(int i,int j) {
    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}

int f[1005];
int fd(int x) {
    if(!f[x])
        return x;
    return f[x]=fd(f[x]);
}

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    for(int i=1; i<=n; i++) {
        scanf("%d%d", &x[i], &y[i]);
    }
    for(int i=1; i<=n; i++) {
        for(int j=i+1; j<=n; j++) {
            Addedge(i, j, dis(i, j));
        }
    }
    sort(E+1, E+cut+1, [](Edge &a, Edge &b) {
        return a.w<b.w;
    });
    int tot=0;
    for(int i=1; i<=cut; i++) {
        int x=fd(E[i].f), y=fd(E[i].to);
        if(x!=y) {
            tot++;
            f[x]=y;
        }
        if(tot==n-k+1) {
            printf("%.2f\n", E[i].w);
            break;
        }
    }

    return 0;
}

posted @   liweihang  阅读(224)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
Live2D
欢迎阅读『[JSOI2010]GROUP 部落划分 GROUP 把n个点分成k个集, 集合间最小距离最大 最小生成树变形』
点击右上角即可分享
微信分享提示