博客
关于我
hdu 1875题解
阅读量:322 次
发布时间:2019-03-04

本文共 2354 字,大约阅读时间需要 7 分钟。

这段代码实现了一个最小生成树算法,结合了并查集(Union-Find)数据结构。以下是对代码的详细分析和解释:

代码结构

  • 预定义和初始化:

    • pre[maxn] 数组用于记录每个节点的父节点。
    • node 结构体用于存储边的信息,包括起点、终点和权重。
    • cmp 函数用于对边进行排序,按权重从小到大排序。
  • 并查集操作:

    • init() 初始化所有节点的父节点为自身。
    • find(x) 查找节点 x 的根节点,递归查找并更新父节点。
    • join(x, y) 将节点 x 和 y 合并到同一个集合中。
  • 主函数:

    • 读取输入数据,包括节点坐标和边信息。
    • 计算所有可能的边,并存储在 path 数组中。
    • 对边进行排序。
    • 使用并查集逐一将边加入,直到所有节点连成一棵树。
    • 计算最小生成树的总权重。
  • 代码解释

    • 预定义部分:

      #include 
      #define maxn 10005using namespace std;

      包含了必要的头文件,定义了节点数的最大值 maxn。

    • 结构体定义:

      struct node {    int from, to;    double val;}

      用于存储边的信息,包括起点、终点和权重。

    • 比较函数:

      bool cmp(node a, node b) {    return a.val < b.val;}

      用于对边按权重排序。

    • 初始化函数:

      void init() {    for (int i = 1; i <= maxn; ++i) {        pre[i] = i;    }}

      初始化每个节点的父节点为自身。

    • 查找函数:

      int find(int x) {    if (pre[x] != x) {        pre[x] = find(pre[x]);    }    return pre[x];}

      查找节点 x 的根节点,并进行路径压缩。

    • 合并函数:

      bool join(int x, int y) {    int fx = find(x);    int fy = find(y);    if (fx != fy) {        pre[fx] = fy;        return true;    }    return false;}

      将节点 x 和 y 合并到同一个集合中。

    • 主函数:

      int main() {    int T;    cin >> T;    while (T--) {        init();        int n;        cin >> n;        for (int i = 1; i <= n; ++i) {            cin >> xx[i] >> yy[i];        }        int num = 0;        for (int i = 1; i <= n; ++i) {            for (int j = i + 1; j <= n; ++j) {                double dis = sqrt(pow(xx[i] - xx[j], 2) + pow(yy[i] - yy[j], 2));                if (dis >= 10 && dis <= 1000) {                    path[num].from = i;                    path[num].to = j;                    path[num].val = dis;                    ++num;                }            }        }        sort(path, path + num, cmp);        double ans = 0.0;        for (int i = 0; i < num; ++i) {            if (join(path[i].from, path[i].to)) {                ans += path[i].val;            }        }        int mark = 0;        bool flag = false;        for (int i = 1; i <= n; ++i) {            if (pre[i] == i) {                mark++;            }        }        if (mark > 1) {            flag = true;        }        if (flag) {            printf("oh!\n");        } else {            printf("%.1lf\n", ans * 100);        }    }    return 0;}

      读取输入数据,计算所有可能的边,并存储在 path 数组中。对边进行排序后,使用并查集逐一合并边,直到所有节点连成一棵树。最后计算最小生成树的总权重。

    代码优化建议

    • 路径压缩:在 find 函数中使用路径压缩优化查找和并查集性能。
    • 按权重排序:确保边是按权重从小到大排序,以保证Kruskal算法正确性。
    • 终止条件:检查是否所有节点连通,避免重复计算或错误输出。

    通过以上分析和优化,可以更好地理解和使用这段代码实现的最小生成树算法。

    转载地址:http://fxaq.baihongyu.com/

    你可能感兴趣的文章
    python制作甘特图的基本知识(附Demo)
    查看>>
    python制作一个简单的服务器,【Python】 做一个简单的 http 服务器
    查看>>
    Python到底能做什么?它的优点在哪?
    查看>>
    python利用pytorch库导出图像分割算子
    查看>>
    python利用pyshark监听网卡来抓包其中pyshark中摸索的一些可用参数
    查看>>
    python利用excel分析过杀漏失
    查看>>
    python判断汉字数目
    查看>>
    python判断文件是空的,如果是空的,就删除
    查看>>
    python判断密码是否正确_python密码判断是否符合要求的方法
    查看>>
    python判断字符串包含中文_Python 判断字符串是否包含中文
    查看>>
    python删除第一行_Python 乱码指北:一行删掉根目录
    查看>>
    Python删除列表元素的三种方法
    查看>>
    python初步学习-python数据类型-集合(set)
    查看>>
    python列表生成字典_Python中将字典转换为列表的方法
    查看>>
    python列表对应元素合并为列表及判断一个列表是几维
    查看>>
    python列表去重复后按照顺序_从包含不可共元素的Python列表中删除重复元素,同时保留顺序?...
    查看>>
    python列表前几个_python之列表
    查看>>
    python列表元组
    查看>>
    Python列表/元组/字典和集合使用
    查看>>
    python列表 行列选择_python_pandas_dataframe_行列选择_切片操作
    查看>>