首页 > 编程语言 >Boruvka 算法简记

Boruvka 算法简记

时间:2023-03-20 21:11:07浏览次数:50  
标签:连通 ch int mi 算法 son 简记 Boruvka

这个算法怕是只会存在于模拟赛里了。

Boruvka 算法是用于解决完全图的生成树的一类算法,因为完全图边数很多,因此普通时间复杂度基于边数的做法不适用。Boruvka 算法核心思想是 所有当前的连通块向其他连通块拓展出最小边,直到整张图只剩下一个连通块。

那么这个算法的核心部分非常简单,下面给出伪代码

while 连通块个数 > 1 :
    for 连通块 i :
        mi[i] = i 和 其他连通块连边的最小值
    for 连通块 i :
        if mi[i] 连接的不是同一个连通块 :
            ans += mi[i]
            合并两个连通块,连通块个数减 1

代码看上去非常简单,但是我们可以通过给 mi[i] 设限,因此使用该算法难点主要在考察如何求解 mi[i] 上。

这里给出例题

Xor-MST

给出 \(n\) 个点的完全图,每个点有一个点权 \(a_i\),连接 \(i\) 号点和 \(j\) 号点的代价是 \(a_i\operatorname{xor} a_j\)。求这个图最小生成树的权值。

考虑怎样求 mi[i],对于异或我们当然有两种方案,在本题,因为有合并和删除的关系,我们选择 Trie 树。

我们将所有的 \(a_i\) 建出一棵 Trie 树,将当前连通块 \(S'\) 的 Trie 树与整棵 Trie 树进行对比,设当前节点为 \(u\),如果所有 \(a_i\) 的 Trie 树上,siz_u 比 \(S\) 的 Trie 树上的 siz_{S',u} 要大,那么说明向这边走肯定有一条连接两个不同的连通块的边。可以贪心选择。

#include <bits/stdc++.h>
#define il inline
#define pii pair<int, int>

using namespace std;

const int N = 2e5 + 5;
const int inf = 1061109567;
int a[N], n, mi[N], fa[N], lnk[N];

il int getfa(int u) { return fa[u] ^ u ? fa[u] = getfa(fa[u]) : fa[u]; }

int cnt, ch[N << 6][2], rt[N], son[N << 6], ed[N << 6];

il void insert(int p, int pos, int val)
{
    for (int i = 30; ~i; --i)
    {
        int c = (val >> i) & 1;
        ++son[p];
        if (!ch[p][c]) ch[p][c] = ++cnt;
        p = ch[p][c];
    }
    son[p] = 1;
    ed[p] = pos;
}

il void merge(int &x, int y)
{
    if (!x || !y) return x = x | y, void();
    merge(ch[x][0], ch[y][0]);
    merge(ch[x][1], ch[y][1]);
    son[x] = son[ch[x][0]] + son[ch[x][1]];
    ed[x] = ed[y];
}

il pii query(int all, int p, int val)
{
    int ans = 0;
    for (int i = 30; ~i; --i)
    {
        int c = (val >> i) & 1;
        if (son[ch[all][c]] - son[ch[p][c]] > 0)
            p = ch[p][c], all = ch[all][c];
        else
            ans = ans | (1 << i), p = ch[p][c ^ 1], all = ch[all][c ^ 1];
    }
    return make_pair(ans, ed[all]);
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i], fa[i] = i;
    sort(a + 1, a + n + 1);
    n = unique(a + 1, a + n + 1) - a - 1;
    rt[0] = ++cnt;
    for (int i = 1; i <= n; ++i)
        insert(rt[0], i, a[i]), insert(rt[i] = ++cnt, i, a[i]);
    long long ans = 0;
    while (1)
    {
        memset(mi, 0x3f, sizeof mi);
        bool chg = false;
        for (int i = 1; i <= n; ++i)
        {
            int fx = getfa(i);
            pii tmp = query(rt[0], rt[fx], a[i]);
            int fy = getfa(tmp.second);
            if (fx != fy)
            {
                int z = tmp.first;
                if (z < mi[fx]) mi[fx] = z, lnk[fx] = fy;
                if (z < mi[fy]) mi[fy] = z, lnk[fy] = fx;
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            int fx = getfa(i), fy = getfa(lnk[i]);
            if (mi[i] < inf && fx != fy)
            {
                ans += mi[i], chg = true;
                merge(rt[fx], rt[fy]), fa[fy] = fx;
            }
        }
        if (!chg) break;
    }
    cout << ans << endl;
    return 0;
}

clang-format 跑的格式化因为感觉自己的代码很丑(

可以仔细感受一下这个算法和贪心的妙处。

标签:连通,ch,int,mi,算法,son,简记,Boruvka
From: https://www.cnblogs.com/misterrabbit/p/17237815.html

相关文章

  • [算法课]全面翻新计划!第二周全解
    文章目录​​上课内容​​​​试题A:组队​​​​数据​​​​详细分析​​​​颜老板版本暴力枚举​​​​吐槽​​​​更新版​​​​思路​​​​枚举版本​​​​思路......
  • [算法课]全面翻新计划!第十一周全解
    文章目录​​上课内容​​​​贪心法​​​​例1兑换货币​​​​颜老板代码​​​​更新版​​​​测试数据​​​​博主提示:​​​​注意:​​​​贪心算法的思路:​​​​......
  • 代码随想录算法训练营Day48 动态规划
    代码随想录算法训练营代码随想录算法训练营Day48动态规划|198.打家劫舍213.打家劫舍II337.打家劫舍III198.打家劫舍题目链接:198.打家劫舍你是一个专业的小偷,计划偷......
  • KMP算法
    KMP算法简介一种由Knuth(D.E.Knuth)、Morris(J.H.Morris)和Pratt(V.R.Pratt)三人设计的线性时间字符串匹配算法。该算法主要解决的就是字符串匹配的问题。本文参考前缀......
  • [算法竞赛进阶指南]货舱选址
    来源:《算法竞赛进阶指南》,模板题算法标签排序,贪心题目描述在一条数轴上有N家商店,它们的坐标分别为A1~AN。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都......
  • 数据结构与算法:二叉树专题
    数据结构与算法:二叉树专题​​前言​​​​前提条件​​​​基础知识​​​​二叉树链式存储结构​​​​二叉树中序遍历​​​​二叉树层序遍历​​​​常见编程题​​​​......
  • DJBX33A哈希(Hash)算法
    1DJBX33A算法原理2DJBX33A算法典型实现2.1PHP(zend_string.h)2.2Apache(apr_hash.c)2.3BerkeleyDB(src\hash\hash_func.c)2.4Python(pyhash.c)3DJBX33A......
  • python实现一个遗传算法
    ###################  importrandom#染色体长度CHROMO_LENGTH=20#种群大小POP_SIZE=50#交叉概率CROSS_RATE=0.8#变异概率MUTATE_RATE=0.01#......
  • 基于matlab的CHPSO异质粒子群优化算法仿真
    1.算法描述粒子群优化算法(ParticleSwarmOptimization,PSO)最初由Kenndy和Eberhart博士于1995年提出,是一种有效的随机全局优化技术,具有原理简单、参数少、收敛速度较快......
  • 【通信】基于Matlab模拟自适应SCMA资源调度算法设计
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......