题目链接:http://poj.org/problem?id=2349
最小生成树:
连通一些点,要求边之和最小。
prime 算法
1.选取一个点(一般我就取第一个了,反正最后都是要加入最小生成树中的= =),标记为遍历过。
2.初始化距离数组,值为和1中选取的点的距离。
3.在未遍历的点中,找出与集合中的点距离最近的点x,标记为遍历过。
4.用x跟新距离,即,若集合中未遍历过的点a所对应的距离比其和x的距离小的话,用a和x的距离替代原先a所对应的距离。
重复3,4至所有点遍历过(共n-1次遍历)。
题目意思:
有m个基站,互相之间可以用无线电联系,这m个基站中,有s个基站配备了卫星接收装置,这意味着他们之间也可以用卫星联系。
因为无线电要覆盖的距离越远,需要的价格就越贵,现在需要求解无线电之间最小的距离D,使得所有基站之间都可以联系。
思路:
1.所有基站之间都能联系,求最小距离:即求最小生成树
2.有s个基站可以通过卫星联系,即可以产生s-1条边,要使D最小,那么这s-1条边一定是最小生成树中最大的s-1条边。
所以在生成最小生成树之后,排个序,输出第s大的边即可。
代码如下:
#include<iostream>
#include<math.h>
#include<algorithm>
#define N 505
#define inf 9999999
using namespace std;
bool vis[N];
double low[N],map[N][N];
int n;
struct ori
{
int x,y;
}a[N];
void prime()
{
int i,j,pos;
double min,sum=0,tmp;
memset(vis,0,sizeof(vis));
pos=0;
vis[0]=1;
for(i=0;i<n;i++)
low[i]=(a[0].x-a[i].x)*(a[0].x-a[i].x)+(a[0].y-a[i].y)*(a[0].y-a[i].y);
for(i=0;i<n-1;i++)
{
min=inf;
for(j=0;j<n;j++)
if(j!=pos)
if(!vis[j]&&low[j]<min)
{
min=low[j];
pos=j;
}
vis[pos]=1;
for(j=0;j<n;j++)
if(!vis[j])
{
tmp=(a[pos].x-a[j].x)*(a[pos].x-a[j].x)+(a[pos].y-a[j].y)*(a[pos].y-a[j].y);
if(low[j]>tmp)
low[j]=tmp;
}
}
}
int main()
{
int t,s,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&s,&n);
for(i=0;i<n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
prime();
sort(low,low+n);
printf("%.2lf\n",sqrt(low[n-s]));
}
return 0;
}
很久之前写的代码,最大值还用999999。。。
后来就用0xFFFF了,
但其实因为int在不同的机器上的长度不同,应该使用unsigned(-1)>>1来表示最大值