博客
关于我
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/

    你可能感兴趣的文章
    NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
    查看>>
    NIH发布包含10600张CT图像数据库 为AI算法测试铺路
    查看>>
    Nim教程【十二】
    查看>>
    Nim游戏
    查看>>
    NIO ByteBuffer实现原理
    查看>>
    Nio ByteBuffer组件读写指针切换原理与常用方法
    查看>>
    NIO Selector实现原理
    查看>>
    nio 中channel和buffer的基本使用
    查看>>
    NIO基于UDP协议的网络编程
    查看>>
    NISP一级,NISP二级报考说明,零基础入门到精通,收藏这篇就够了
    查看>>
    Nitrux 3.8 发布!性能全面提升,带来非凡体验
    查看>>
    NI笔试——大数加法
    查看>>
    NLog 自定义字段 写入 oracle
    查看>>
    NLog类库使用探索——详解配置
    查看>>
    NLP 基于kashgari和BERT实现中文命名实体识别(NER)
    查看>>
    NLP 项目:维基百科文章爬虫和分类【01】 - 语料库阅读器
    查看>>
    NLP_什么是统计语言模型_条件概率的链式法则_n元统计语言模型_马尔科夫链_数据稀疏(出现了词库中没有的词)_统计语言模型的平滑策略---人工智能工作笔记0035
    查看>>
    NLP学习笔记:使用 Python 进行NLTK
    查看>>
    NLP的神经网络训练的新模式
    查看>>
    NLP采用Bert进行简单文本情感分类
    查看>>