博客
关于我
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启动脚本
    查看>>
    Python听写汇总结果
    查看>>
    python吊打Excel?屁!那是你不会用!
    查看>>
    Python合并两张图片 | 先叠透明度再合并 (附Demo)
    查看>>
    python各进制的表述与转换
    查看>>
    python各种库安装
    查看>>
    python可视化matplotlib_如何使用Python中最强大的可视化工具Matplotlib?
    查看>>
    python可维护性_使用这7大神器,让你的Python 代码更容易于维护
    查看>>
    Python只运行一次while循环
    查看>>
    python变量的详细教程_Python零基础入门教程之语法入门[变量](第二期)
    查看>>
    Python变量命名方法-ChatGPT4o作答
    查看>>
    Python变量与运算符
    查看>>
    Python变量/运算符/函数/模块/string
    查看>>
    python发送邮件的时候出现 error (535, b‘5.7.3 Authentication unsuccessful‘) 解决方法
    查看>>
    python系列【仅供参考】:python flask框架 debug功能
    查看>>
    python发送notes邮件_使用python在Lotus Notes中发送邮件
    查看>>
    Python双版本下创建一个Scrapy(西瓜皮)项目
    查看>>
    Python双版本下No module named 'requests'
    查看>>
    python及pycharm2018软件安装教程
    查看>>
    python去重txt文本_Python实现的txt文件去重功能示例
    查看>>