• 【二分答案/最小生成树】部落划分(洛谷P4047)


    题目描述

    输入

    第一行包含两个整数N、K,分别描述野人居住点的数量和部落的数量。
    接下来N 行,每行包含两个整数xi, yi,描述了一个居住点的坐标。

    输出

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

    数据范围限制

    Solution:

    第一眼看到最小最大就秒写二分答案,结果爆精度了QAQ

    正解有两个,一个是二分答案,不难发现单调性,二分结果,check的时候就判断各个点之间距离是否有小于二分出来答案的,有就把两点合并,运用并查集即可解决,但是要注意精度问题(详见代码)

    另一个说是最小生成树,其实是运用类似于kruscal的思想,sort点点之间边的长度,然后从最小的开始判断,并使用并查集将它们合并,同时动态更新并查集数量,当并查集数量等于K即划分完毕

    Code(二分答案):

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int N,K,Book[10005],Ans,fa[10005];
     4 double Dis[1005][1005],X[10005],Y[10005];
     5 int find(int x)
     6 {
     7     if(fa[x]==x) return x;
     8     else return fa[x]=find(fa[x]);
     9 }
    10 bool Check(double T){
    11     Ans=0;
    12     for(int i=1;i<=N;i++) fa[i]=i;
    13     for(int i=1;i<=N;i++) Book[i]=0;
    14 //    double Test=T+0.005;
    15     for(int i=1;i<N;i++)
    16         for(int j=i+1;j<=N;j++){
    17             if(T>Dis[i][j]){
    18                 int fx=find(i),fy=find(j);
    19                 if(fx!=fy)
    20                     fa[fx]=fy;
    21             }
    22         }
    23     for(int i=1;i<=N;i++){
    24         int father=find(i);
    25         if(!Book[father]){
    26             Ans++;
    27             Book[father]=1;
    28         }
    29     }
    30     if(Ans>=K) return true;
    31     else return false;
    32     
    33 }
    34 int main()
    35 {
    36 //    freopen("tribe.in","r",stdin);
    37 //    freopen("tribe.out","w",stdout);
    38     scanf("%d%d",&N,&K);
    39     for(int i=1;i<=N;i++)
    40         scanf("%lf%lf",&X[i],&Y[i]);
    41     for(int i=1;i<=N;i++)
    42         for(int j=1;j<=N;j++){
    43             Dis[i][j]=sqrt((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]));
    44     //        Dis[i][j]+=0.005;
    45         }
    46     double L=0.0001,R=200000000.00,Res=0;
    47     while(L-R<=0.0001){
    48         double Mid=(L+R)/2;
    49         if(Check(Mid)){
    50             Res=Mid;
    51             L=Mid+0.0001;
    52         }
    53         else
    54             R=Mid-0.0001;
    55     }
    56 
    57     printf("%.2lf",Res);
    58     return 0;
    59 }
  • 相关阅读:
    Git标签使用技巧
    Git入门基本概述
    过滤器+缓存在.NET5WebApi项目中的简单使用
    在.NET5中 使用JWT鉴权授权
    Git常用开发命令
    时间戳的实际使用
    两个日期字段相减,进行计算
    MQ的理论理解
    第一周学习C语言的总结!
    问题(the question)
  • 原文地址:https://www.cnblogs.com/Takarada-Rikka/p/13556293.html
Copyright © 2020-2023  润新知