标签:最小生成树 图论 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