• BZOJ1821 [JSOI2010] Group 部落划分 Group


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1821

    Description

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

    Input

    第一行包含两个整数N和K(1< = N < = 1000,1< K < = N),分别代表了野人居住点的数量和部落的数量。
    接下来N行,每行包含两个正整数x,y,描述了一个居住点的坐标(0 < =x, y < =10000)

    Output

    输出一行,为最优划分时,最近的两个部落的距离,精确到小数点后两位。

    贪心,把边权小的边划分到部落内部,第n - k + 1条边的边权就是答案。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #define rep(i,l,r) for(int i=l; i<=r; i++)
     7 #define clr(x,y) memset(x,y,sizeof(x))
     8 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
     9 using namespace std;
    10 const int INF = 0x3f3f3f3f;
    11 const int maxn = 1010;
    12 inline int read(){
    13     int ans = 0, f = 1;
    14     char c = getchar();
    15     for(; !isdigit(c); c = getchar())
    16     if (c == '-') f = -1;
    17     for(; isdigit(c); c = getchar())
    18     ans = ans * 10 + c - '0';
    19     return ans * f;
    20 }
    21 struct Edge{
    22     int from,to;
    23     double cost;
    24     inline bool operator < (const Edge &_Tp) const{
    25         return cost < _Tp.cost;
    26     }
    27 }edge[500010];
    28 struct Point{
    29     int x,y;
    30 }t[maxn];
    31 int n,k,cnt=0,tot=0,fa[maxn];
    32 inline double getdis(Point a,Point b){
    33     return sqrt((a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y));
    34 }
    35 inline void addedge(int x,int y,double dis){
    36     edge[++cnt].from = x; edge[cnt].to = y; edge[cnt].cost = dis;
    37 }
    38 int getfa(int x){
    39     return fa[x] == x ? x : fa[x] = getfa(fa[x]);
    40 }
    41 int main(){
    42     n = read(); k = read();
    43     rep(i,1,n) t[i].x = read(), t[i].y = read(), fa[i] = i;
    44     rep(i,1,n-1) rep(j,i+1,n) addedge(i,j,getdis(t[i],t[j]));
    45     sort(edge+1,edge+cnt+1);
    46     k = n - k;
    47     rep(i,1,cnt){
    48         int a = getfa(edge[i].from), b = getfa(edge[i].to);
    49         if (a == b) continue;
    50         fa[a] = b;
    51         if (++tot > k){
    52             printf("%.2lf
    ",edge[i].cost);
    53             return 0;
    54         }
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    寄存器(内存访问)知识整理
    寄存器知识点
    汇编语言之实验一
    汇编语言基础知识的总结
    汇编语言之第五章至第八章知识汇总
    汇编实验之第八章数据处理的两个基本问题
    汇编语言之第七章更灵活的定位内存地址的方法
    汇编语言之实验九
    汇编语言之第六章包含多个段的程序
    汇编语言之第五章【BX】和loop指令
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj1821.html
Copyright © 2020-2023  润新知