这个题是个典型的最小生成树的题目,但是刚开始怎么都过不了,后来发现两种写法都有疏忽,但是prim的到目前为止不懂为什么刚开始的不对,kruskal算法,并查集的初始条件从0开始写成从1开始了,所以已知wa,还有这个题比最小生成树一个卡点就是处理两点之间的距离的时候,要保证点都在10-1000之间。其它的没有什么坑了。
代码一(prim)
#include <stdio.h> #include <string.h> #include <math.h> #define INFI 999999999.0 using namespace std; const int N = 130; typedef struct point { int x, y; }point; double Map[N][N]; point p[N]; int vis[N]; double ans; double low_cost[N]; double calc(int a, int b) { return sqrt((p[b].y - p[a].y) * (p[b].y - p[a].y) + (p[b].x - p[a].x) * (p[b].x - p[a].x)); } void calc_distance(int n) { memset(Map, 0, sizeof(Map)); double t; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { t = calc(i, j); if (t >= 10 && t <= 1000) Map[i][j] = Map[j][i] =calc(i, j); else Map[i][j] = Map[j][i] = INFI; } } } int prim(int n) { for (int i = 0; i < n; i++) low_cost[i] = Map[0][i]; vis[0] = 1; for (int i = 1; i < n; i++) { int k = 0; double min = INFI; for (int j = 1; j < n; j++) { if (!vis[j] && min > low_cost[j]) { min = low_cost[j]; k = j; } } if (k != 0) { vis[k] = 1; ans += min; } else return 0; for (int j = 1; j < n; j++) { if (!vis[j] && Map[k][j] < low_cost[j]) low_cost[j] = Map[k][j]; } } return 1; } int main() { int T, C; scanf("%d", &T); while (T--) { memset(vis, 0, sizeof(vis)); ans = 0.0; scanf("%d", &C); for (int i = 0; i < C; ++i) scanf("%d %d", &p[i].x, &p[i].y); calc_distance(C); int t = prim(C); if (t == 0) { puts("oh!"); continue; } ans *= 100.0; printf("%.1f\n", ans); } return 0; }