搜索与图论(三)——最小生成树、二分图

前言

算法基础课-3.4
第三章 搜索与图论(三)

共4题,知识点如下:
最小生成树:
Prim算法求最小生成树、
Kruskal算法求最小生成树。
二分图:
染色法判定二分图、
匈牙利算法—二分图的最大匹配。

掌握模版的最核心部分是:记住算法思路

不能纯记模版,效率很低,一定要记思路

可以想到啥算法,就自己把算法流程描述一遍

最小生成树

稠密图一般用朴素版Prim(主要是代码较短)

稀疏图一般用Kruskal算法(思路更简单而且代码也比堆优化版Prim少)

堆优化版Prim一般不会用到(也是适用于稀疏图)

在这里插入图片描述

堆优化版Prim和堆优化版Dijkstra,优化方式是一样的

所以略过,只讲朴素版Prim 和 Kruskal(实用主义,用到再学,用不到就暂时不学)

朴素版prim算法

朴素版Prim算法和Dijkstra非常相似

Dijkstra

先初始化,迭代n次,每次都找距离最近的点t(不在集合中的),然后用它更新其他点,再把它放到集合里去。
集合:(已经确定最短距离的点)

在这里插入图片描述

Prim

集合s:在当前连通块里的所有点

在这里插入图片描述
区别:

Dijkstra 是用 t 更新到起点的距离
Prim 是用 t 更新到集合的距离
t:不在集合中的距离最近的点

模板

时间复杂度是 O(n2+m), n 表示点数,m 表示边数

int n;      // n表示点数
int g[N][N];        // 邻接矩阵,存储所有边
int dist[N];        // 存储其他点到当前最小生成树的距离
bool st[N];     // 存储每个点是否已经在生成树中


// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成树的树边权重之和
int prim()
{
   
    memset(dist, 0x3f, sizeof dist);

    int res = 0;
    for (int i = 0; i < n; i ++ )
    {
   
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        if (i && dist[t] == INF) return INF;

        if (i) res += dist[t];
        st[t] = true;

        for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);
    }

    return res;
}

模板题 AcWing 858. Prim算法求最小生成树

初始
在这里插入图片描述
随便挑一个更新到其他点的距离,然后将该点加入集合
在这里插入图片描述在这里插入图片描述
2(离集合最近的点)更新其他所有点,距离没有更短,没变化,加入到集合中
在这里插入图片描述
然后用3更新,最后用4,距离都没有变短,保持不变
在这里插入图片描述
最小生成树,最短的几条边(相等的任选一条即可)
在这里插入图片描述

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
// 点500,边10w,稠密图,用邻接矩阵存
const int N = 510, INF = 0x3f3f3f3f;

int n, m;
int g[N][N];
int dist[N]; // 点到集合的距离
bool st[N];

int prim() {
   
    // 1.初始化
    memset(dist, 0x3f, sizeof dist);
    // 2.n次迭代
    int res = 0; // 存最小生成树的树边权重之和
    for (int i = 0; i < n; i++) {
   
        // 1) 每次找到集合外的所有点中距离最小的点
        int t = -1;
        for (int j = 1; j <= n; j++) {
   
            // !st[j]:集合外,t == -1:还没找到任何点, dist[t] > dist[j] : t的距离比j大
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        
        // i!=0&&dist[t] == INF 当前距离最近的点到集合距离都是+∞,说明图是不连通的
        if (i && dist[t] == INF) return INF;
        // 只要不是第一个点,就把答案加上
        if (i) res += dist[t]; // 需要先累加再更新,防止把自环的加进去了
        
        // 2)用t更新其他点到集合的记录
        for (int j = 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值