思路:最小生成树+prim
分析:
1 由于点有1000,如果要用kruskal的话最少有1000000条边,所以我么选择用prim算法
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; }