题目地址: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);
}
}