最小生成树

最小,生成 · 浏览次数 : 9

小编点评

**算法流程:** 1. 初始化所有距离为正无穷,保存已经选的点集合。 2. 遍历所有点,找到距离最小的点并加入集合。 3. 对于每个点,更新其距离所有点距离的最小值。 4. 如果当前点距离所有点距离已达到最大值,则无法加入集合,返回不符合条件。 5. 遍历所有连接当前点的边,如果这条边与当前选出的边不在同一个集合中,则加入集合并更新其距离。 6. 返回最小生成树的边数。 **Kruskal算法的流程:** 1. 将所有边按照权值从小到大排序。 2. 遍历所有边,如果这条边与当前选出的所有边不在同一个集合中,则加入集合并更新其距离。 3. 选择具有最小距离的边,直到选出了N-1条边。 4. 如果当前边数不等于N-1,则无法构造最小生成树,返回不符合条件。 5. 返回最小生成树的边数。 **时间复杂度:** * 最小生成树算法:O(n * log(m)) * Kruskal算法:O(n * log(m))

正文

什么是最小生成树

给定一个图,在图中选择N - 1条边(N代表图的点数)把图的所有节点都连起来,且边的权值最小,则这N - 1条边就是原图的最小生成树。

如何求最小生成树

求最小生成树有两种算法:

  1. prim

  2. kruskal

prim算法

其实本质上和dijstra算法很像。

适用于稠密图。

题目:

image

算法流程:

  1. 将所有点到已经选的点的集合的距离设为正无穷。

  2. 每次找到dis最小的点,加入到集合中。

  3. 使用该点的距离更新所有点到集合距离(注意:我们之前已经确定过的点不需要再被改变dis,所以说我们要特殊确定一下)。

代码:

#include <bits/stdc++.h>
#define N 510
using namespace std;
int n, m;
int g[N][N];
int dis[N];
bool st[N];
int prim() {
    memset(dis, 0x3f, sizeof dis);
    dis[1] = 0;
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        int minid = -1; //	dis最小的点
        for (int j = 1; j <= n; ++j)
            if (!st[j] && (minid == -1 || dis[j] < dis[minid]))
                minid = j;
        if (dis[minid] == 0x3f3f3f3f)
            return 0x3f3f3f3f; //	不符合条件
        ans += dis[minid];
        st[minid] = true;
        for (int j = 1; j <= n; ++j)
            dis[j] = min(dis[j], g[minid][j]); //	更新距离
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    memset(g, 0x3f, sizeof g);
    cin >> n >> m;
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    int t = prim();
    if (t == 0x3f3f3f3f)
        puts("impossible");
    else
        cout << t << '\n';
    return 0;
}

kruskal算法

适用于稀疏图。

题目:

image

前置知识:并查集

如果不会并查集,可以看我的另外一篇博客:【数据结构】并查集

算法流程:

  1. 将所有边按照权值从小到大排序。
  2. 如果这条边与之前选出来的所有边不会形成环(使用并查集判断),那么就使用这条边,否则舍去这条边。
  3. 直到选出了N-1条边,算法结束。

代码:

#include <bits/stdc++.h>
#define N 100010
using namespace std;
int p[N]; //  并查集
struct Egde {
    int a, b, c;
    bool operator<(const Egde& t) const {
        return c < t.c;
    } //  按边权从小到大排序
} edges[N * 2];
int n, m;
int cnt, ans;
int find(int x) {
    if (p[x] != x)
        p[x] = find(p[x]);
    return p[x];
}
void kruskal() {
    for (int i = 1; i <= m; ++i) {
        int a = find(edges[i].a), b = find(edges[i].b), c = edges[i].c;
        if (a != b) {
            ans += c;
            cnt++;
            p[a] = b;
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        p[i] = i;
    for (int i = 1; i <= m; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        edges[i] = {a, b, c};
    }
    sort(edges + 1, edges + m + 1);
    kruskal();
    if (cnt < n - 1) { //  选出的边数不是N-1条,不符合条件
        puts("impossible");
        return 0;
    }
    cout << ans << '\n';
    return 0;
}

与最小生成树相似的内容:

最小生成树

## 什么是最小生成树 给定一个图,在图中选择N - 1条边(N代表图的点数)把图的所有节点都连起来,且边的权值最小,则这N - 1条边就是原图的最小生成树。 ## 如何求最小生成树 求最小生成树有两种算法: 1. prim 2. kruskal ## prim算法 其实本质上和dijstra算法很

学习笔记——斯坦纳树

斯坦纳树 斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种。最小生成树是在给定的点集和边中寻求最短网络使所有点连通。而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小。 百度百科 在图论里,一般用于解决形如: 给定一个连通图 \(G\),给定 \(k\) 个关键点,选取

算法学习笔记(30):Kruskal 重构树

Kruskal 重构树 这是一种用于处理与最大/最小边权相关的一个数据结构。 其与 kruskal 做最小生成树的过程是类似的,我们考虑其过程: 按边权排序,利用并查集维护连通性,进行合并。 如果我们在合并时,新建一个节点,其权值为当前处理的边的权值,并将合并的两个节点都连向新建的节点,那么就可以得

Solution -「LOJ #3310」丁香之路

首先有两个前置技巧:1) 两点间的最短距离就是直接连接两点的边的长度;2) 遍历一个子图的最小花费是最小生成树的边权之和乘二。原问题让我们找出一条最短且必经过钦定边的 \(( s, i )\) 路径,那么我们先将 \(\lang s , i \rang\) 连上,问题就变成了找出一条最短且必经过钦定

C#实现生成Markdown文档目录树

前言 之前我写了一篇关于C#处理Markdown文档的文章:C#解析Markdown文档,实现替换图片链接操作 算是第一次尝试使用C#处理Markdown文档,然后最近又把博客网站的前台改了一下,目前文章渲染使用Editor.md组件在前端渲染,但这个插件生成的目录树很丑,我魔改了一下换成boots

决策树

# 决策树相关概念及简单实现 ​ 决策树是一种机器学习的方法。决策树的生成算法有ID3(信息增益), C4.5(信息增益率)和CART(Gini系数)等。决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。 ​ 构造树的基本想法

Part-DB 配置流程

介绍 Part-DB是一个开源的器件管理工具,博主用于管理个人的电子器材,最近捣鼓了一下这个工具,由于手头还有一块闲置的赛昉·星光2的开发板,所以我打算一起拿来捣鼓一下,如果不成功,就用树莓派(生气) 1.安装 大家可以直接按照 官方安装指导 来安装即可,我也是参考官方的。 (1)安装docke

【技术积累】《MongoDB实战》笔记(1)

《MongoDB实战》笔记 第一章 为现代Web而生的数据库 特性 mongodb适合做水平扩展的数据库。 mongodb把文档组织成集合,无schema。 索引 mongodb的二级索引是B树实现。 每个集合最多可以创建64个索引, 副本集 mongodb通过副本集(replication set

算法学习笔记(11): 原根

原根 此文相对困难,请读者酌情食用 在定义原根之前,我们先定义其他的一点东西 阶 通俗一点来说,对于 $a$ 在模 $p$ 意义下的阶就是 $a^x \equiv 1 \pmod p$ 的最小正整数解 $x$ 或者说,$a$ 在模 $p$ 意义下生成子群的阶(群的大小) 再或者说,是 $a$ 在模

next-route

在目录结构中,我们精心创建的每一个文件最终都会经过处理,转化为相应的页面路由。然而,值得注意的是,某些特殊文件格式在生成过程中并不会被当作路由路径来处理。 app |-auth login page.tsx password page.tsx //最后生成的路由路径 //·localhost:300