图论篇2——最小生成树算法(kurskal算法&prim算法)

本文介绍了最小生成树的概念,包括树、生成树和最小生成树。详细阐述了Kruskal算法和Prim算法,分别解析了两种算法的基本思想、步骤和时间复杂度。总结了Kruskal适合稀疏图,Prim适合稠密图,堆优化后的Prim理论上具有更快的时间复杂度。
摘要由CSDN通过智能技术生成

基本概念

(Tree)

如果一个无向连通图中不存在回路,则这种图称为树。

生成树 (Spanning Tree)

无向连通图G的一个子图如果是一颗包含G的所有顶点的树,则该子图称为G的生成树。

生成树是连通图的极小连通子图。这里所谓极小是指:若在树中任意增加一条边,则将出现一条回路;若去掉一条边,将会使之变成非连通图。

最小生成树

一个带权值连通图用$n-1$条边把$n$个顶点连接起来,且连接起来的权值最小

应用场景

设想有9个村庄,这些村庄构成如下图所示的地理位置,每个村庄的直线距离都不一样。若要在每个村庄间架设网络线缆,若要保证成本最小,则需要选择一条能够联通9个村庄,且长度最小的路线。

 

Kruskal算法

知识点:数据结构——并查集

基本思想

始终选择当前可用、不会(和已经选取的边)构成回路的最小权植边。

具体步骤:

1. 将所有边按权值进行降序排序

2. 依次选择权值最小的边

3. 若该边的两个顶点落在不同的连通分量上,选择这条边,并把这两个顶点标记为同一连通分量;若这条边的两个顶点落到同一连通分量上,舍弃这条边。反复执行2,3,直到所有的都在同一连通分量上。【这一步需要用到上面的并查集】

模板题:https://www.luogu.org/problem/P3366

#include <iostream>
#include <algorithm>
using namespace std;
int pre[5005];
int n, m; //n个定点,m条边

struct ENode {
    int from, to, dis;
    bool operator<(ENode p) {
        return dis < p.dis;
    }
}M[200005];

int Find(int x) {
    return x == pre[x] ? pre[x] : pre[x] = Find(pre[x]);
}

int kurskal() {
    sort(M, M + m);
    int N = n, res = 0;
    for (int i = 0; i < m && N > 1; i++) {
        int fx = Find(M[i].from), fy = Find(M[i].to);
        if (fx != fy) {
            pre[fx] = fy;
            N--;//找到了一条边,当N减到1的时候表明已经找到N-1条边了,就完成了
            res += M[i].dis;
        }
    }
    if (N == 1)//循环做完,N不等于1 表明没有找到合适的N-1条边来构成最小生成树
        return res;
    return -1;
}

int main() {
    cin >> n >>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值