zoukankan      html  css  js  c++  java
  • BZOJ1821: [JSOI2010] Group 部落划分 (kruskal)

    BZOJ1821: [JSOI2010] Group 部落划分 

    Description

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

    Input

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

    Output

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

    Sample Input

    4 2
    0 0
    0 1
    1 1
    1 0


    Sample Output

    1.00
     
     
    题解:
    一开始看题目以为是二分答案,后来想想看根本不需要,直接 kruskal 就水过去了
    一开始每个点为一个个体,总部落数为 n ,我们先把两两点之间连边,从小打大排序,然后按 kruskal 做,加入了一条边,当前部落总数 -1,直到部落数为 k 时跳出,剩下的最小的未被加入的边就是最终答案(因为前面更小的边已经包含到部落中去了,这个肯定是最大值)。
    本题代码不难,思想上需要下点功夫。
     
    上代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1005;
     4 int n,k,edge,x[N],y[N],fa[N];
     5 struct node{
     6     int x,y;
     7     double w;
     8 }e[N*N];
     9 bool cmp(node a,node b)
    10 {
    11     return a.w<b.w;
    12 }
    13 int sqr(int x)
    14 {
    15     return x*x;
    16 }
    17 int getf(int x)
    18 {
    19     return fa[x]==x?x:(fa[x]=getf(fa[x]));
    20 }
    21 void add(int a,int b)
    22 {
    23     double ww=sqrt(sqr(x[a]-x[b])+sqr(y[a]-y[b]));
    24     e[++edge].w=ww;
    25     e[edge].x=a,e[edge].y=b;
    26 }
    27 int main()
    28 {
    29     scanf("%d%d",&n,&k);
    30     for (int i=1; i<=n; i++)
    31       scanf("%d%d",&x[i],&y[i]);
    32     for (int i=1; i<=n-1; i++)
    33       for (int j=i+1; j<=n; j++)
    34           add(i,j);
    35     sort(e+1,e+1+edge,cmp);
    36     for (int i=1; i<=n; i++)
    37       fa[i]=i;
    38     for (int i=1; i<=edge; i++)
    39     {
    40         int u=getf(e[i].x),v=getf(e[i].y);
    41         if (u!=v)
    42         {
    43             if (n>k) {
    44                 n--;
    45                 fa[u]=v;
    46             }
    47             else {
    48                 printf("%.2lf",e[i].w); return 0;
    49             }
    50         }
    51     }
    52     return 0;
    53 }
    View Code

    加油加油加油!!! fighting fighting fighting !!!

     
  • 相关阅读:
    part11-1 Python图形界面编程(Python GUI库介绍、Tkinter 组件介绍、布局管理器、事件处理)
    part10-3 Python常见模块(正则表达式)
    Cyclic Nacklace HDU
    模拟题 Right turn SCU
    状态DP Doing Homework HDU
    Dp Milking Time POJ
    区间DP Treats for the Cows POJ
    DP Help Jimmy POJ
    Dales and Hills Gym
    Kids and Prizes Gym
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9211914.html
Copyright © 2011-2022 走看看