题意:
国防部(DND)要用无线网络连接北部几个哨所。两种不同的通信技术被用于建立网络:每一个哨所有一个无线电收发器,一些哨所将有一个卫星频道。
任何两个有卫星信道的哨所可以通过卫星进行通信,而不管他们的位置。同时,当两个哨所之间的距离不超过D时可以通过无线电通讯,D取决于对收发器的功率。功率越大,D也越大,但成本更高。出于采购和维修的方便,所有哨所的收发器必须是相同的;那就是说,D值对每一个哨所相同。
你的任务是确定收发器的D的最小值。每对哨所间至少要有一条通信线路(直接或间接)。
题解:
因为是要将所有哨所联接起来,所以肯定是要用最小生成树的,我用的是Kruskal算法,然后S的作用是可以帮你减少S-1条边,如果要找到尽可能小的D的话,我们可以用最小生成树的思想去想,因为每次都是找到树中最小的边,那么当我们找到第n-1-(s-1)条边的时候我们就可以输出这个值了,这个值肯定是属于最小生成树的最小边并且是用去了卫星剩下的最大边了。
然后。。。我WA了好几次,后来发现,我是每次在跑一次就m++(m代表的是生成树里现在的边数),应该是放在判断不是同一根节点时m才++的。之后还WA。。。就把%0.2lf改成%0.2f就过了,POJ的机器。。。。ORZ
//Kruskal
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int MAXN=505*505;
struct node1
{
int u,v;
double l;
}map[MAXN];
struct node2
{
double x,y;
}a[505];
int fa[505];
int n,s,k;
bool cmp(node1 c,node1 d)
{
return c.l<d.l;
}
int find(int p)
{
return fa[p]==p? p:fa[p]=find(fa[p]);
}
void Kruskal()
{
double sum=0;
int m=s-1,t=0;
for(int i=0;i<k;i++)
{
int P=find(map[i].u);
int Q=find(map[i].v);
if(P!=Q)
{
sum=map[i].l;
fa[P]=Q;
m++;
if(m>=n-1)
break;
}
}
printf("%0.2f\n",sum);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
k=0;
scanf("%d%d",&s,&n);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
map[k].u=i;
map[k].v=j;
map[k].l=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
k++;
}
sort(map,map+k,cmp);
Kruskal();
}
}