UVA_10369
题目的大概意思是,两个地点如果各有一个satellite channel,那么无论它们相隔多远都能通信,而如果任何一个没有satellite channel的话,就只能靠radio通信,而radio通信的成本与距离D是成正比的,现在希望让所有地点都能直接或者间接通信,问最小的D是多少。
这个题目实际上是在求一个最小生成森林的最长边,今天刚看到吉大模板上的最小生成森林,没想到立刻就用上了。
最小生成树有两个特点,一个是保证了所有边的和是最小值,另一个是保证了所有边中的最大值最小。由于Kruskal算法每选中一条边就相当于把两个点集合并成了一个点集,最后用n-1条边连成了1个点集。那么我们往回推,n-2条边就连成了2个点集,n-3条边就连成了3个点集……而就这道题而言,我们相当于去求一共有N个点集的最小生成森林,只要取够P-N条边即可。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
double x[510],y[510],w[250010];
int u[250010],v[250010],r[250010],p[510];
double distance(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int find(int x)
{
return p[x]==x?x:(p[x]=find(p[x]));
}
int cmp(const void *_p,const void *_q)
{
int *p=(int *)_p;
int *q=(int *)_q;
return w[*p]>w[*q]?1:-1;
}
int main()
{
int i,j,k,N,P,n,e,t,tx,ty;
double ans;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&N,&P);
for(i=0;i<P;i++)
scanf("%lf%lf",&x[i],&y[i]);
n=0;
for(i=0;i<P;i++)
for(j=i+1;j<P;j++)
{
u[n]=i;
v[n]=j;
w[n]=distance(i,j);
n++;
}
for(i=0;i<n;i++)
r[i]=i;
qsort(r,n,sizeof(r[0]),cmp);
for(i=0;i<P;i++)
p[i]=i;
k=0;
for(i=0;i<n;i++)
{
e=r[i];
tx=find(u[e]);
ty=find(v[e]);
if(tx!=ty)
{
p[tx]=ty;
ans=w[e];
k++;
}
if(k==P-N)
break;
}
printf("%.2f\n",ans);
}
return 0;
}