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

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

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

代码结构

  • 预定义和初始化

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

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

    • 读取输入数据,包括节点坐标和边信息。
    • 计算所有可能的边,并存储在 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;}

      将节点 xy 合并到同一个集合中。

    • 主函数

      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/

    你可能感兴趣的文章
    Network-Emulator Network-Emulator-Toolkit网络模拟器使用
    查看>>
    Networkx写入Shape文件
    查看>>
    NetworkX系列教程(11)-graph和其他数据格式转换
    查看>>
    Networkx读取军械调查-ITN综合传输网络?/读取GML文件
    查看>>
    NetworkX:是否为每个节点添加超链接?
    查看>>
    network小学习
    查看>>
    Netwox网络工具使用详解
    查看>>
    Net与Flex入门
    查看>>
    Net任意String格式转换为DateTime类型
    查看>>
    net包之IPConn
    查看>>
    net发布的dll方法和类显示注释信息(字段说明信息)[图解]
    查看>>
    Net和T-sql中的日期函数操作
    查看>>
    Net处理html页面元素工具类(HtmlAgilityPack.dll)的使用
    查看>>
    Net操作Excel(终极方法NPOI)
    查看>>
    Net操作配置文件(Web.config|App.config)通用类
    查看>>
    net网络查看其参数state_dict,data,named_parameters
    查看>>
    Net连接mysql的公共Helper类MySqlHelper.cs带MySql.Data.dll下载
    查看>>
    NeurIPS(神经信息处理系统大会)-ChatGPT4o作答
    查看>>
    neuroph轻量级神经网络框架
    查看>>
    Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(7)
    查看>>