坑了我半个晚上的一道题~
就是最小生成树而已,难点就是这道题的题意~
题目大意:
有s个卫星,p个农场,(1<=s<=p<=500)每个农场有一个无线发射器,无线发射器和卫星可以使两个农场直接通信,无线发射器有覆盖范围,范围越大成本越大,现在要节约成本,用卫星将一些农场连起来,问这些农场连起来后无线发射器最少的覆盖范围.
解题思想:
题意最后的意思就是用卫星连起来的几个点可以缩成一个点,然后再求把所有点连起来的通信线路中的最大的那条路.那么首先创建一课生成树,求所有点连通后所有最小边,也就是求生成树过程中的dis数组.将所有边排序,将权值最大的s-1个点合并,那么最大覆盖距离是dis[p-s];
源代码:
#include <myhead.h>
const int N=510;
struct Node{
int x,y;
};
int n,m;
bool make[N];
double dis[N];
double graph[N][N];
Node node[N];
void addNode(int i,int x,int y) {
node[i].x=x;
node[i].y=y;
}
double pre(const Node &a,const Node &b) {
double x=abs(a.x-b.x);
double y=abs(a.y-b.y);
return sqrt(x*x+y*y);
}
void init() {
scanf("%d%d",&m,&n);
memset(make,false,sizeof(make));
for(int i=0;i<n;++i) {
dis[i]=(double)INT_MAX;
}
memset(graph,0,sizeof(graph));
int x,y;
for(int i=0;i<n;++i) {
scanf("%d%d",&x,&y);
addNode(i,x,y);
}
for(int i=0;i<n;++i) {
for(int j=i+1;j<n;++j) {
graph[i][j]=graph[j][i]=pre(node[i],node[j]);
}
}
}
void prim() {
int q;
double minvalue;
dis[0]=0.0;
for(int k=1;k<n;++k) {
minvalue=(double)INT_MAX;
for(int i=0;i<n;++i) {
if(!make[i]&&minvalue>dis[i]) {
minvalue=dis[i];
q=i;
}
}
make[q]=true;
for(int i=0;i<n;++i) {
if(!make[i]) {
checkmin(dis[i],graph[q][i]);
}
}
}
sort(dis+1,dis+n);
printf("%.2lf\n",dis[n-m]);
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
init();
prim();
}
return 0;
}