1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| 分析: 1 由于点有1000,如果要用kruskal的话最少有1000000条边,所以我么选择用prim算法 2 题目中的点的坐标最大值为10^6,那么如果在平方一下的话会超过int,所以在求两个 点之间的距离的时候用在前面乘上一个1.0这样就表示的double从而不会超过int了。 3 题目中的说了,要用64位的浮点数,所以选择用double 。输出的时候是“%0.2Lf”,不知道为啥long double才能过
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <iostream> using namespace std; #define MAXN 1010 #define INF 0x3f3f3f3f
int n, m; int vis[MAXN]; long double mp[MAXN][MAXN]; long double lowcost[MAXN];
struct Point{ int x; int y; }p[MAXN];
void init() { long double tmp_x, tmp_y; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ tmp_x = 1.0 * (p[i].x - p[j].x) * (p[i].x - p[j].x); tmp_y = 1.0 * (p[i].y - p[j].y) * (p[i].y - p[j].y); mp[i][j] = sqrt(tmp_x + tmp_y); } } }
void prime() { int pos; long double ans = 0.0; memset(vis, 0, sizeof(vis)); vis[1] = 1; for(int i = 1; i <= n; i++){ lowcost[i] = mp[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] > mp[j][pos]){ lowcost[j] = mp[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 j = 1; j <= m; j++){ scanf("%d%d", &x, &y); mp[x][y] = mp[y][x] = 0; } prime(); return 0; }
|