公路修建 link
思路:
如图,对于任意一点A,因为它申请修建AB道路,因此离A最近的点一定是B
同理,B申请修建BC道路,因此C一定比A离B更近(即C在圆B内,不包含边界)
同时,C申请修建CA道路,即A离C比A离B更近
满足题意的话,ABC只能组成正三角形,因此排除最短边有三种情况
因为题目有:一个实数,四舍五入保留两位小数,表示公路总长。(保证有唯一解)。
所以限制二是没有的!
本题另外一个问题在于空间的限制上, 5000 * 5000的空间大小会MLE
那么我们发现题目给的是坐标,所以我们想到可以不直接存储距离,
而是在Prim的运行流程中把距离即时计算出来即可。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 5000 + 10;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
struct node { int x, y; }point[MAXN];
double ans, dis[MAXN];
bool vis[MAXN];
int n;
double calc(int a, int b) {
return sqrt((double)(point[a].x - point[b].x) * (point[a].x - point[b].x) + (double)(point[a].y - point[b].y) * (point[a].y - point[b].y));
}
int main() {
n = read();
for(int i = 1; i <= n; ++i) {
point[i].x = read(), point[i].y = read();
dis[i] = 1e8;
}
int pos; dis[1] = 0;
for(int i = 1; i <= n; ++i) {
double minn = 1e8;
for(int j = 1; j <= n; ++j) if(!vis[j] && dis[j] < minn) {
minn = dis[j]; pos = j;
}
ans += minn; vis[pos] = true;
for(int j = 1; j <= n; ++j) {
double d = calc(pos, j);
if(d < dis[j]) dis[j] = d;
}
}
printf("%.2lf\n", ans);
return 0;
}