首页 > 其他分享 >图论——最小生成树 学习笔记

图论——最小生成树 学习笔记

时间:2023-11-15 16:12:23浏览次数:34  
标签:图论 idx int graph 最小 笔记 vector res dis

图论——最小生成树 学习笔记

本文仅对于无向连通图。

生成树,Spanning Tree(ST),在一个 \(n\) 个点的图中选取 \(n-1\) 条边,构成一棵树。

最小生成树,Minimum Spanning Tree(MST),通常是边权和最小的生成树。

算法分类:

算法 Prim Prim 堆优化 Kruskal
思想 加点 加点 加边
时间复杂度 \(\mathcal O(n^2+m)\) \(\mathcal O(m \log n)\) \(\mathcal O(m\log m)\)

实际应用中,Kruskal 往往更好些、且更快。即使是对于稠密图,Prim 的理论复杂度更优,Kruskal 也不一定跑的慢。

如果不是明显卡一个算法的,可以 Kruskal 解决。

Kruskal

思想:加边,贪心选择。

思路为,将所有边 \((u,v,w)\) 按权值 \(w\) 排序,从小到大依次遍历,如果两侧不属于一个连通块,那么就将这条边加入生成树中。最终一定会选出 \(n-1\) 条边,且是一个最小生成树。

证明:略,见 OI-Wiki

Prim

思想:加点,贪心选择。

思路为,每次选择距离最小的一个结点,并用新的边更新其他结点的距离。

和 Dijkstra 算法类似,因此可以堆优化。

时间复杂度:\(\mathcal O(n^2+m)\),堆优化 \(\mathcal O((n+m) \log n)\)。

代码

struct edge { int u, v, w; };
bool operator <(const edge &a, const edge &b) { return a.w < b.w; }

struct graph_vector {
    vector<edge> e;
    graph_vector() { e.clear(); }
    graph_vector(int m) { e.resize(m); }
};

struct graph_array {
    vector<vector<int>> e;
    graph_array() { e.clear(); }
    graph_array(int n) { e.resize(n + 1, vector<int>(n + 1, INF)); }
};

struct graph_list {
    vector<int> h, e, w, ne; int idx;
    graph_list() { idx = 0; }
    graph_list(int n, int m) {
        h.resize(n + 1); idx = 0;
        e.resize(m + 1), ne.resize(m + 1), w.resize(m + 1);
    } void add(int u, int v, int s) {
        ++idx; e[idx] = v; w[idx] = s; ne[idx] = h[u];
        h[u] = idx;
    } void Add(int u, int v, int w) { add(u, v, w); add(v, u, w); }
};

struct dsu {
    vector<int> f;
    dsu(int n) { f.resize(n + 1); iota(f.begin(), f.end(), 0); }
    int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
    bool merge(int a, int b) {
        a = find(a), b = find(b);
        return a == b ? 0 : (f[find(a)] = f[find(b)], 1);
    }
};

struct {
    int mst(int n, graph_vector &g) {
        sort(g.e.begin(), g.e.end());
        int res = 0, cnt = 0;
        dsu d(n); for (auto &i: g.e) {
            int u = i.u, v = i.v;
            if (!d.merge(u, v)) continue;
            res += i.w, ++cnt;
            if (cnt == n - 1) return res;
        } return -1;
    } int mst(int n, graph_array &g) {
        vector<int> dis(n + 1), vis(n + 1);
        fill(dis.begin(), dis.end(), INF);
        int res = 0; rep(i, n) {
            int t = -1; gor(j, 1, n + 1)
            if (!vis[j] && (t == -1 || dis[j] < dis[t])) t = j;
            if (i && dis[t] == INF) return -1;
            if (i) res += dis[t];
            gor(j, 1, n + 1) dis[j] = min(dis[j], g.e[t][j]);
            vis[t] = 1;
        } return res;
    } int mst(int n, graph_list &g) {
        vector<int> dis(n + 1), vis(n + 1);
        fill(dis.begin(), dis.end(), INF);
        priority_queue<pii, vector<pii>, greater<pii>> heap;
        heap.push({0, 1}); dis[1] = 0;
        int res = 0, cnt = 0; while (heap.size()) {
            int u = heap.top().second, d = heap.top().first;
            heap.pop(); if (vis[u]) continue;
            res += d; vis[u] = 1, ++cnt;
            for (int i = g.h[u]; i; i = g.ne[i]) {
                int v = g.e[i], w = g.w[i];
                if (w < dis[v]) dis[v] = w, heap.push({w, v});
            }
        } return cnt == n ? res : -1;
    }
} mst;

标签:图论,idx,int,graph,最小,笔记,vector,res,dis
From: https://www.cnblogs.com/RainPPR/p/mst.html

相关文章

  • 第十二章学习笔记、知识完整性总结
    摘要:本章讨论了块设备I/O和缓冲区管理;解释了块设备I/O的原理和I/O缓冲的优点;论述了Unix的缓冲区管理算法,并指出了其不足之处;还利用信号量设计了新的缓冲区管理算法,以提高I/O缓冲区的缓存效率和性能;表明了简单的PV算法易于实现,缓存效果好,不存在死锁和饥饿问题;还提出了一个......
  • 学习笔记419—如何快速从Github下载文件
    如何快速从Github下载文件从国内下载Github文件的速度往往会很慢,因此有一些开发者提供了代理下载功能,这些服务都是免费的,你甚至可以通过开源代码自建Github下载官网:https://d.serctl.com这是一个简单干脆的Github文件代下网站,提供八个下载节点,你可以从中选择最快的节点下载 使用方......
  • 硬件开发笔记(十一):Altium Designer软件介绍、安装过程和打开pcb工程测试
    前言  前面做高速电路,选择是阿li狗,外围电路由于读者熟悉AD,使用使用ad比较顺手,非高速电路就使用AD了,其实AD也可以做高速电路,由于笔者从13年开始做硬是从AD9开始的,所以开始切入AD做硬件软件学习成本会低很多。 AltiumDesigner简介  AltiumDesigner是原Protel软......
  • 软件设计开发笔记5:QT开发三参数温室气体数据记录软件
      最近有一个为三参数温室气体分析仪及其多通道换向阀箱编写数据记录和控制的需求。所以在这一篇中我们就来分析一下如何使用QT实现这一需求。1、需求分析  虽然说传递过来的需求只有“实现一个三参数温室气体分析仪及其多通道换向阀箱的数据记录和控制”这样一句话,但所有人都......
  • 第五周阅读笔记|人月神话————削足适履-关注程序的空间规模和空间控制技能
    削足适履这个章节在讲什么?我们很多时候在开发程序的时候都是考虑程序的运行时间和效率,而很少考虑到程序的运行空间问题。现在的存储空间是越来越廉价,我们很少去考虑这些问题。经典的DOS版本的仙剑奇侠传还不到20M,而现在的一个大游戏却是2,3G甚至更大。由于计算机的不断更新换代和......
  • 图论——最短路 学习笔记
    图论——最短路学习笔记其实是复习性质的,主要是总结,证明什么的,等上大学再说。定义单源最短路:从一个点\(q\)出发,到其他所有点的最短路。全源最短路:任意两点见最短路。算法对比算法FloydJohnsonBellman–FordSPFADijkstra类型全源全源单源单源单源......
  • 数据结构——字典树 学习笔记
    数据结构——字典树学习笔记字典树,也叫trie树。检索字符串本质是记录字符串前缀的一棵查找树,形态类似于:字典树使用边表示字母,节点表示一个前缀,同时也可以在节点上记录状态\(\mathit{tag}\)。基本实现形如:var: nex[0..siz][0..rng],idx est[0..siz],pre[0..siz]fun......
  • 偏序问题学习笔记
    前提给若干个\(n\)维的点,对于每个点求出每一维均小于等于它的点的数量。按字典序排序,然后预处理相同的点,这样后面的点不可能对前面的点产生贡献。如果某个点后面有与其相同的点,那么当前点的贡献就会少算,所以我们需要提前在当前点的答案中加上后面与其相同的点的数量。经过这......
  • 密码学笔记
    密码算法:对称密码算法、非对称密码算法、摘要算法对称密码算法:加密秘钥和解密秘钥相同的密码算法又称秘密秘钥算法或单秘钥算法分组密码算法(BlockCipher):块加密算法将明文拆分为N个固定长度的明文块用相同的秘钥和算法对每个明文块加密得到N个等长的密文块然后将N个......
  • uniapp开发笔记
    控件toast控件uni.showToast({icon:'none',title:'输入topic'})注意点引入图片需要的注意事项图片的宽度不能是auto相对路径和绝对路径绝对路径要以/开头示例代码{bigUrl:"static/image/img/Children.jpg",data:[{......