思路:最小生成树+prime
分析:
1 由于点有1000,如果要用kruskal的话最少有1000000条边,所以我么选择用peime算法
2 题目中的点的坐标最大值为10^6,那么如果在平方一下的话会超过int,所以在求两个点之间的距离的时候用在前面乘上一个1.0这样就表示的double从而不会超过int了。
3 题目中的说了,要用64位的浮点数,所以选择用long double 。输出的时候是“%0.2Lf”。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 1010
int n , m;
int vis[MAXN];
long double lowcost[MAXN];
long double G[MAXN][MAXN];
struct Point{
int x;
int y;
}p[MAXN];
void init(){
for(int i = 1 ; i <= n; i++){
for(int j = 1 ; j <= n ; j++){
long double tmp_x = 1.0*(p[i].x-p[j].x)*(p[i].x-p[j].x);/*这里注意乘上一个1.0*/
long double tmp_y = 1.0*(p[i].y-p[j].y)*(p[i].y-p[j].y);/*这里注意乘上一个1.0*/
G[i][j] = sqrt(tmp_x + tmp_y);
}
}
}
void prime(){
int pos;
long double ans = 0;
memset(vis , 0 , sizeof(vis));
vis[1] = 1;
for(int i = 1 ; i <= n ; i++)
lowcost[i] = G[1][i];
for(int i = 1 ; i <= n ; i++){
pos = -1;
for(int j = 1 ; j <= n ; j++){
if(!vis[j] && (pos == -1 || lowcost[j] < lowcost[pos]))
pos = j;
}
if(pos == -1)
break;
ans += lowcost[pos];
vis[pos] = 1;
for(int j = 1 ; j <= n ; j++){
if(!vis[j] && lowcost[j] > G[j][pos])
lowcost[j] = G[j][pos];
}
}
printf("%0.2Lf\n" , ans);/*注意输出的格式*/
}
int main(){
int x , y;
scanf("%d%d" , &n , &m);
for(int i = 1 ; i <= n ; i++)
scanf("%d%d" , &p[i].x , &p[i].y);
init();
for(int i = 0 ; i < m ; i++){
scanf("%d%d" , &x , &y);
G[x][y] = G[y][x] = 0;
}
prime();
return 0;
}