博客
关于我
cf 1095f kruskal模板题 kruskal适合稀疏图 prim适合稠密图
阅读量:293 次
发布时间:2019-03-03

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

为了解决这个问题,我们需要找到一种方法,使得在给定的点和额外边的条件下,连接所有点的总代价最小。我们可以使用Kruskal算法来解决这个问题,因为它适合处理稀疏图。

方法思路

  • 问题分析:我们需要连接所有的点,使得任意两点之间的代价最小。每个点有一个权值,原图中每个点对之间有一条边,边的权值是两个点的权值之和。我们还可以选择额外的边来替代这些边,从而降低总代价。

  • 关键思路:找到权值最小的点t,将其他所有点连接到t。这样,连接t到其他点的边的权值是最小的。然后,剩下的边选择权值最小的边来连接其他点。

  • 算法选择:使用Kruskal算法来找到最小生成树。Kruskal算法适合处理稀疏图,时间复杂度为O(m log m),适合处理大规模数据。

  • 实现步骤:

    • 找到权值最小的点t。
    • 构造边集合,包括额外边和t与其他点之间的边。
    • 使用Kruskal算法在边集合中找到最小生成树的总权值。
  • 解决代码

        

    题意:

    n个点,每个点有一个权值node[i],在第i个点和第j个点之间连无向边的代价为node[i]+node[j],有m条额外边可选择,第u个点和第v个点连无向边的代价为w,额外边可以用可以不用。问连边使任意两点可连通的总代价是多少。

    数据范围:1 ≤ n ≤ 2e5 , 0 ≤ m ≤ 2e5。

    题解:

    1. 使用Kruskal算法求最小生成树。

    2. 找到权值最小的点t,将除t之外的点和t相连,原有的边与m条额外边共同组成可选的边集合E。

    3. n ≤ 2e5,由于边是无向的且包括原有的边和额外边,总边数cnt ≤ 8e5,远小于2e5 * 2e5,是稀疏图,使用Kruskal算法。

    4. Prim算法复杂度O(n²)不适合,Kruskal算法复杂度O(m log m)适合。

        #include 
    #define N 800005 using namespace std; int n, m, cnt = 0; long long node[N]; int pre[N]; struct Edge { int u, v; long long weight; }; int find(int x) { if (x == pre[x]) return pre[x]; pre[x] = find(pre[x]); return pre[x]; } bool cmp(const Edge &a, const Edge &b) { return a.weight < b.weight; } void kruskal() { int i, j; int u, v; int ru, rv; long long sum = 0; sort(edges, edges + cnt, cmp); for (i = 0; i < cnt; ++i) { u = edges[i].u; v = edges[i].v; ru = find(u); rv = find(v); if (ru == rv) continue; pre[ru] = rv; sum += edges[i].weight; } cout << sum << endl; } int main() { int i, j; Edge a; scanf("%d%d", &n, &m); for (i = 1; i <= n; ++i) { scanf("%lld", &node[i]); if (node[i] < min_node) { min_node = node[i]; t = i; } pre[i] = i; } for (i = 1; i <= n; ++i) { if (i == t) continue; a.u = t; a.v = i; a.weight = node[t] + node[i]; edges[cnt++] = a; a.u = i; a.v = t; edges[cnt++] = a; } for (i = 1; i <= m; ++i) { scanf("%d%d%lld", &u, &v, &w); a.u = u; a.v = v; a.weight = w; edges[cnt++] = a; a.u = v; a.v = u; edges[cnt++] = a; } kruskal(); }

    代码解释

  • 读取输入:读取点数n和额外边数m,然后读取每个点的权值,找到权值最小的点t。
  • 构造边集合:构造边集合,包括t与其他点之间的边,以及额外的边。
  • Kruskal算法:对边集合进行排序,使用并查集算法找到最小生成树的总权值。
  • 这个方法确保了在给定的约束条件下,连接所有点的总代价最小。

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

    你可能感兴趣的文章
    python3----ASCII
    查看>>
    Python3-selenium自动化测试框架,结合HTMLTestRunner测试报告!
    查看>>
    Python3-如何自我更新作为服务运行的应用程序
    查看>>
    Python3.1-网格模拟概念性问题
    查看>>
    Python3.12 解决conda环境libstdc++版本过低问题
    查看>>
    python3.2批量查询IP地址区域
    查看>>
    Python3.5中协程和未来/任务之间的区别?
    查看>>
    python3.5实现socket通讯(TCP)
    查看>>
    python3.6 ubuntu部署nginx、 uwsgi、 django
    查看>>
    Python3.6.3中,functools似乎不能用
    查看>>
    python3.6.5+cuda9+cudnn7.1+win10+tensorflow-gpu1.9.0下载配置
    查看>>
    python3.6使用pickle序列化class
    查看>>
    python3.6入门到高阶(全栈) day027 网络通信协议 osi七层模型
    查看>>
    Python3.6属性错误:模块‘;异步没有属性‘;运行‘;
    查看>>
    python3.6版本中的python-weka-wrapper安装失败,错误代码为%1
    查看>>
    Python3.7安装cv2踩过的坑
    查看>>
    python写txt文件
    查看>>
    python关于sorted排序函数详细解析 附实战代码(全)
    查看>>
    python3.8调用m文件,调用matlab
    查看>>
    python3.9新特性_Python 3.9 新特性速览
    查看>>