题意:有两种不合的通信技巧,有卫星通信的两个城市之间可以随便率性联络,但用无线电通信的城市只能和间隔不跨越D的城市接洽。无线电的才能越高(即传输间隔D越大),花费就越大。已知无线电的数量m,让求最小的D。
之前自己写的prim算法是O(n^3)的,当写到这道题TLE过后,我才发觉我的算法写的很挫,本来PRIM应该是O(n^2)的,所以又重写写了一下,把这题给A了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#define MAXN 550
#define INF 100000000
using namespace std;
typedef struct{
double x,y;
}point;
point pt[MAXN];
double map[MAXN][MAXN];
bool visited[MAXN];
double LowValue[MAXN];//生成树到所在集合U到各个顶点的多条边中最短的一条
vector<double> usedValue;
double cal_dis(point p1, point p2){
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
double prim(int n,int s){
usedValue.clear();
int st;
double minV;
memset(visited,0, sizeof(visited));
visited[0] = 1;
for(int i = 1; i < n ;i++){
LowValue[i] = map[0][i];
}
for(int i = 0; i < n - 1; i++){
minV = INF;
for(int j = 0; j < n; j++){
if(!visited[j] && LowValue[j] < minV){
minV = LowValue[j];
st = j;
}
}
visited[st] = 1;
//printf("st:%d\n",st);
usedValue.push_back(minV);
for(int j = 0; j < n; j++){
if(!visited[j] && map[st][j] < LowValue[j]) LowValue[j] = map[st][j];
}
}
int len = usedValue.size();
sort(usedValue.begin(), usedValue.end());
//printf("s:%d len:%d\n", s, len);
//for(int i = 0;i < len; i++) printf("%.3f\n",map[0][1]);
return usedValue[len - s];
}
int main(){
int t, s, p;
while(scanf("%d", &t) != EOF){
while(t--){
scanf("%d%d", &s, &p);
for(int i = 0; i < p; i++){
scanf("%lf%lf", &pt[i].x, &pt[i].y);
}
for(int i = 0 ; i < p; i++){
for(int j = i; j<p; j++){
map[i][j]= map[j][i] = cal_dis(pt[i], pt[j]);
}
}
double result = prim(p,s);
printf("%.2f\n", result);
}
}
return 0;
}