Description
国防部(DND)要用无线网络连接北部几个哨所。两种不同的通信技术被用于建立网络:每一个哨所有一个无线电收发器,一些哨所将有一个卫星频道。
任何两个有卫星信道的哨所可以通过卫星进行通信,而不管他们的位置。同时,当两个哨所之间的距离不超过D时可以通过无线电通讯,D取决于对收发器的功率。功率越大,D也越大,但成本更高。出于采购和维修的方便,所有哨所的收发器必须是相同的;那就是说,D值对每一个哨所相同。
你的任务是确定收发器的D的最小值。每对哨所间至少要有一条通信线路(直接或间接)。
Input
输入的第一行是测试数据的数量N。
每组测试数据的第一行包含卫星频道的数量S(1 < = S < = 100)和哨所的数量P(S < P < = 500)。接下来的P行,给出以公里为单位的每个哨所的坐标(x,y)( 坐标为0到10000之间的整数)。
Output
对于每组测试数据,输出一行,输出收发器的D的最小值。精确到小数点后两位。
Sample Input
1
2 4
0 100
0 300
0 600
150 750
Sample Output
212.13
有卫星(k个卫星)的两个哨所可以随便通信,先跑一次最小生成树(kruskal),再对生成树的边(n条边)从小到大排序,去掉比较大的n-k条边。
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cstdlib>
const int MAXN=505;
const int INF=0x7fffffff;
const int MAXM=250005;
int fa[MAXN];
double le[MAXM];
double x[MAXN];
double y[MAXN];
int mark=0;
bool vis[MAXN];
struct Edge
{
int u,v;
double w;
}edge[MAXM],tree[MAXM];
int tol;
int p;
using namespace std;
void add(int u,int v,double w)
{
edge[tol].u=u;
edge[tol].v=v;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int find (int x)
{
if(fa[x]==-1)
return x;
else return fa[x]=find(fa[x]);
}
double kruskal(int n)
{
memset(fa,-1,sizeof(fa));
sort(edge,edge+tol,cmp);
int cnt=0;
double ans=0;
for(int i=0;i<tol;i++)
{
int u=edge[i].u;
int v=edge[i].v;
double wei=edge[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
ans+=wei;
le[mark]=wei;
//tree[mark].u=u;
//tree[mark].v=v;
//tree[mark].w=w;
mark++;
fa[t1]=t2;
cnt++;
}
if(cnt==n-1)break;
}
//printf("%f\n",ans);
if(cnt<n-1)
return -1;
else
return ans;
}
int main (void)
{
int t,n;
cin>>t;
while(t--)
{
memset(vis,false,sizeof(vis));
scanf("%d %d",&n,&p);
for(int i=1;i<=p;i++)
{
scanf("%lf %lf",&x[i],&y[i]);
}
tol=0;
for(int i=1;i<=p;i++)
{
double d;
for(int j=1;j<=i;j++)
{
if(i==j)
{
d=INF;
}
else
{
d=sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
add(i,j,d);
}
}
double re=kruskal(p);
//for(int i=0;i<n-1&&mark>0;i++)
// re-=le[mark--];
printf("%.2f\n",le[mark-n]);
}
return 0;
}