标签:最小生成树 图论 kruskal 并查集 hdu1162
题目如下:
3 1.0 1.0 2.0 2.0 2.0 4.0
3.41
题目大意:
给出n个点的坐标(二维x, y),可以使用直线(无向的)将任意两个点连接起来,求将所有点连接起来形成一个整体(使任何两点之间可达),线的最小距离。
一个简单的最小生成树问题,这里边的权要根据输入的点的坐标信息求出,在输入的时候存储点的数组中下标可以认为是该点的编号,通过O(n^2)的复杂度来求任意两个不同点之间的距离作为权,边的两个顶点就是这段距离两端点的编号。则接下来就是简单的最小生成树算法了,可以使用kruskal也可以使用prim。
kruskal算法实现
#include <cstdio> #include <vector> #include <algorithm> #include <cmath> using namespace std; const int N = 105; struct Edge { int x, y; double w; }; struct Point { double x; double y; }; int pre[N]; Point point[N]; Edge edges[N * N / 2]; int i_p, i_e, cnt; double res; int root(int x) { if (x != pre[x]) { pre[x] = root(pre[x]); } return pre[x]; } bool merge(int x, int y) { int fx = root(x); int fy = root(y); bool ret = false; if (fx != fy) { pre[fx] = pre[fy]; ret = true; --cnt; } return ret; } void init(int n) { cnt = n; res = 0; for (int i = 0; i <= n; ++i) { pre[i] = i; } } bool cmp(const Edge &a, const Edge &b) { return a.w < b.w; } int main() { int n; double dx, dy; while (scanf("%d", &n) != EOF) { init(n); i_e = i_p = 0; for (int i = 0; i < n; ++i) { scanf("%lf %lf", &dx, &dy); point[i_p].x = dx; point[i_p].y = dy; ++i_p; } for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { edges[i_e].x = i; edges[i_e].y = j; double dd = (point[i].x - point[j].x) * (point[i].x - point[j].x); dd += (point[i].y - point[j].y) * (point[i].y - point[j].y); edges[i_e].w = sqrt(dd); ++i_e; } } sort(edges, edges + i_e, cmp); //the cnt == 1 indicates that the mixnum spanning tree is builded sucessfully. for (int i = 0; i < i_e && cnt != 1; ++i) { if (merge(edges[i].x, edges[i].y))res += edges[i].w; } printf("%.2lf\n", res); } return 0; }
HDU 1162 Eddy's picture(图论-最小生成树)
标签:最小生成树 图论 kruskal 并查集 hdu1162
原文地址:http://blog.csdn.net/iaccepted/article/details/42612453