poj 2349 Arctic Network 并查集 连通分支数,二分答案

题目地址:poj2349

题目思路:S实际上就是最后最佳答案对应的连通分支数(额,一开始没有理解为什么不是S+1,最后发现...每一个连通分支都要对应一个啊)

然后二分答案,如果当前的D使得连通分支<S, 那么D太大了,= 的情况应该并入这一类。

额,INF设置的太大会TLE 刚好是最远距离就行。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>

const double eps=1e-8;

using namespace std;




struct edge
{
    int u;
    int v;
    double  w;
   
};




edge e[250000];
int  fa[505];

int  find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
bool  edge_cmp(edge a,edge b)
{
    return a.w<b.w;
}

int n,m;

int cc;



int calc_cc()
{
    for(int i=0;i<m;i++)
    {
        if(cc==1)  break;
        int x=find(e[i].u);
        int y=find(e[i].v);
        
        if(x!=y)
        {
            fa[x]=y;
            
            cc--;
           
        }
    }
    
    return cc;
}



void   init()
{
    for(int i=0;i<n;i++)
    {
        fa[i]=i;
    }
    cc=n;

}

struct Point
{
    double x;
    double y;
    Point(double x=0,double y=0):x(x),y(y) {}
    
};

typedef  Point  Vector;

Vector  operator-(Point A,Point B)
{
    return  Point(A.x-B.x,A.y-B.y);
}

double Length(Vector A)
{
    return sqrt(A.x*A.x+A.y*A.y);
}

Point read_point()
{
    Point A;
    scanf("%lf%lf",&A.x,&A.y);
    return A;
}

int S,P;

Point p[505];


int main()
{
    int T;
    cin>>T;
    while(cin>>S>>n)
   {
       for(int i=0;i<n;i++)
       {
           p[i]=read_point();
       }
       
       double l=0,r=30000;
      
       
       double mid;
        while(r-l>1e-4)
       {
           mid=l+(r-l)/2;
           init();
          
           int cnt=0;
           for(int i=0;i<n;i++)
               for(int j=i+1;j<n;j++)
               {
                   if(Length(p[i]-p[j])<=mid)
                   {
                       e[cnt].u=i;
                       e[cnt].v=j;
                       cnt++;
                   }
               }
           m=cnt;
           
           int c_c=calc_cc();
           if(c_c<=S)
           {
               r=mid;
           }
           else
           {
              l=mid;
           }
          
       }
       
       printf("%.2f\n",mid);
   }
    
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值