((蓝桥杯 刷题全集)【备战(蓝桥杯)算法竞赛-第4天(搜索与图论-下 专题)】( 从头开始重新做题,记录备战竞赛路上的每一道题 )距离蓝桥杯还有63天

news2024/11/28 16:41:10

🏆🏆🏆🏆🏆🏆🏆
欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)
 
文章字体风格:
红色文字表示:重难点✔★
蓝色文字表示:思路以及想法✔★
 
如果大家觉得有帮助的话,感谢大家帮忙
点赞!收藏!转发!

 
我的qq号是:1210931886,欢迎大家加群,一起学习,互相交流,共同进步🎉🎉✨✨
🥇🥇🥇🥇🥇🥇🥇

蓝桥杯系列,为大家提供

  1. 做题全集,备战蓝桥杯,就做这个系列的题即可
  2. 一个大概的做题规划——大家最好在此基础上提前两个月准备

备战蓝桥杯就刷这些题
第一天博客链接 - 基础算法 -上
第二天博客链接 - 基础算法 -下 + 数据结构专题
第三天博客链接 - 搜索与图论-上 专题
第四天博客链接 - 搜索与图论-下 专题
第五天博客链接 - 数学知识专题
第六天博客链接 - 动态规划 专题
第七天博客链接 - 贪心算法 专题

蓝桥杯 刷题全集

  • 9. spfa 算法
        • 1. spfa求最短路 ✔12.24
        • 做题总结:
  • 10. spfa判断负权回路
      • 例题 spfa判断负环 ✔12.26
        • 刷题总结
  • 11. floyd算法( 两两之间最短距离 )
        • 1. Floyd求最短路 ✔12.26
          • 做题总结
  • 12. 朴素版prim算法
        • 1. Prim算法求最小生成树
            • 做题总结
  • 13. Kruskal算法
        • 1. Kruskal算法求最小生成树( 利用并查集 )
  • 14. 染色法判别二分图
        • 染色法判定二分图 ✔ 12.28
          • 算法思路 + 做题总结
  • 15. 匈牙利算法
      • 模板
        • 二分图的最大匹配 ✔12.29
          • 做题总结:

9. spfa 算法

1. spfa求最短路 ✔12.24

原题链接

做题总结:

  1. 和宽搜差不多,只是可能会 返回走(但距离值更新了,就把这个节点入队列再处理一次)
#include<iostream>
#include<cstring>
#include<queue>

using namespace std;

const int N = 1e5+10;
int e[N],ne[N],h[N],idx;
int w[N];

bool st[N];

int n,m;

void add(int x,int y,int c)
{
    e[idx] = y,ne[idx] = h[x],w[idx] = c,h[x] = idx++;
}

int d[N];

void spfa()
{
    memset(d,0x3f,sizeof d);
    d[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    while(q.size())
    {
        auto f = q.front();
        q.pop();
        st[f] = false;
        for(int i = h[f]; i != -1; i = ne[i])
        {
            int j = i;
            if(d[e[j]] > d[f] + w[j])
            {
                d[e[j]] = d[f] + w[j];
            if(st[e[j]]==false)
            {
                q.push(e[j]);
                st[e[j]] = true;
            }
                
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    memset(h,-1,sizeof h);
    for(int i = 0; i < m; i++)
    {
        int x,y,c;
        cin >> x >> y >> c;
        add(x,y,c);
    }
    
    spfa();
    if(d[n] == 0x3f3f3f3f)
        cout << "impossible";
    else
        cout << d[n];
    return 0;
}

10. spfa判断负权回路

原题链接

  1. 什么是负环
    在这里插入图片描述
    图1中:2 到 3 到 4 到 2 路径长度为 -10
    图2中:2 到 3 到 4 到 2 路径长度为 10

图1才叫负环
图2不是负环

  1. 出现负环会怎么样
    但出现负环的时候,如果我们要去求1到n的最短路,那么过程中,一定会在这个负环中一直转圈,导致路程可以变为负无穷

  2. 怎么判断图中是否有负环?
    综上,我们就采取求最小路径的方式(但是本题不是求最短路),当我们求最短路径的过程中,发现有一段路径重复走,那么就说明一定出现了负环

问题来了:怎么判断某段路径在重复走
我们想,1到n号点 最多才可能走了n-1条边
如果我们发现 到某点时 已经走了 大于等于n条边,那么一定就是有负环了
由于我们不知道 1 到 x点最多可能有多少条边,但一定不会超过 n - 1 条边,所以我们就都用 大于等于n条边去判断

例题 spfa判断负环 ✔12.26

原题链接

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

using namespace std;

const int N = 2010, M = 10010;

int n, m;
int h[N], w[M], e[M], ne[M], idx;
int dist[N], cnt[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

bool spfa()
{
    queue<int> q;

    for (int i = 1; i <= n; i ++ )
    {
        st[i] = true;
        q.push(i);
    }

    while (q.size())
    {
        int t = q.front();
        q.pop();

        st[t] = false;

        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                cnt[j] = cnt[t] + 1;

                if (cnt[j] >= n) return true;
                if (!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }

    return false;
}

int main()
{
    scanf("%d%d", &n, &m);

    memset(h, -1, sizeof h);

    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }

    if (spfa()) puts("Yes");
    else puts("No");

    return 0;
}

刷题总结

  1. e,ne,h,idx 用于存储边,所以数值应该与边一样多
  2. 把所有点都入队列,防止不是连通图
  3. dist里存储多少都可以,因为我们只需判断负权回路
  4. 当一个点所走的路径长度大于n,那么就一定有负边,因为最多就是n正常的话。
  5. 一定要有st数组,判断是否再走这个点

11. floyd算法( 两两之间最短距离 )

在这里插入图片描述

1. Floyd求最短路 ✔12.26

原题链接

做题总结
  1. 用二维数组存储更方便
  2. 读入存储的时候,读取最小值,并且到自身值为0
  3. Floyd
#include<iostream>
#include<cstring>

using namespace std;
int n,m,k;
const int N = 210;
int d[N][N];

void Floyd()
{
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
}

int main()
{
    cin >> n >> m >> k;
    memset(d,0x3f,sizeof d);
    for(int i = 0; i < m; i++)
    {
        int x,y,c;
        cin >> x >> y >> c;
        d[x][y] = min(d[x][y], c);
        d[x][x] = 0;
        d[y][y] = 0;
    }
    Floyd();
    for(int i = 0; i < k; i++)
    {
        int x,y;
        cin >> x >> y;
        if(d[x][y]>=0x3f3f3f3f/2)
            cout << "impossible" << endl;
        else
            cout << d[x][y] << endl;
    }
    
    return 0;
}

12. 朴素版prim算法

1. Prim算法求最小生成树

原题链接

做题总结

1. 和dijk算法差不多 只是 dist数组存储的是 到联通块的距离

#include<iostream>
#include<cstring>

using namespace std;

const int N = 510;
int p[N][N], d[N];
int n, m;
bool st[N];
int res;
int sum;

void prim()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;

    for (int k = 0; k < n; k++)
    {
        int t = -1;

        for (int l = 1; l <= n; l++)
        {
            if (st[l] == false && (t == -1 || d[t] > d[l]))
                t = l;
        }
        if (d[t] == 0x3f3f3f3f)
        {
            res++;
            return;
        }
        st[t] = true;
        sum += d[t];
        for (int i = 1; i <= n; i++)
        {
            d[i] = min(d[i], p[t][i]);
        }
    }
}

int main()
{
    memset(p,0x3f,sizeof p);
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y, c;
        cin >> x >> y >> c;
        p[x][y]= p[y][x] = min(p[x][y],c);
    }
    prim();
    if (res)
        cout << "impossible";
    else
        cout << sum;
    return 0;
}

13. Kruskal算法

在这里插入图片描述

1. Kruskal算法求最小生成树( 利用并查集 )

原题链接
原题链接

在这里插入图片描述

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

using namespace std;

const int N = 100010, M = 200010, INF = 0x3f3f3f3f;

int n, m;
int p[N];

struct Edge
{
    int a, b, w;

    bool operator< (const Edge &W)const
    {
        return w < W.w;
    }
}edges[M];

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int kruskal()
{
    sort(edges, edges + m);

    for (int i = 1; i <= n; i ++ ) p[i] = i;    // 初始化并查集

    int res = 0, cnt = 0;
    for (int i = 0; i < m; i ++ )
    {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;

        a = find(a), b = find(b);
        if (a != b)
        {
            p[a] = b;
            res += w;
            cnt ++ ;
        }
    }

    if (cnt < n - 1) return INF;
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);

    for (int i = 0; i < m; i ++ )
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }

    int t = kruskal();

    if (t == INF) puts("impossible");
    else printf("%d\n", t);

    return 0;
}

14. 染色法判别二分图

在这里插入图片描述

染色法判定二分图 ✔ 12.28

算法思路 + 做题总结

算法思路

  1. 通过dfs 一个染1 另一个染2(通过3-c)
  2. dfs需要有返回值。所以当 下一个返回来的是false,那么就返回false
    所以一个dfs中,通过判断有一个return false,并且还有一个根据下一个的return 再return false

做题总结

  1. 无向图 需要开辟 2倍

原题链接

原题链接

#include<iostream>
#include<cstring>

using namespace std;

const int N = 2e5+10;

int e[N],ne[N],h[N],idx;
int color[N];
bool st[N];
int n,m;

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

bool dfs(int x,int c)
{
    st[x] = true;
    color[x] = c;
    for(int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(st[j]==true)
        {
            if(color[j]==color[x])
                return false;
        }
        if(st[j] == false)
        {
            if(!dfs(j,3-c))
                return false;
        }
    }
    return true;
}

int main()
{
    cin >> n >> m;
    memset(h,-1,sizeof h);
    
    for(int i = 0; i < m; i++)
    {
        int x,y;
        cin >> x >> y;
        add(x,y),add(y,x);
    }
    
    bool flag = false;
    for(int i = 1; i <= n; i++)
    {
        if(st[i]==false)
        {
            if(!dfs(i,1))
            {
                flag = true;
                break;
            }
        }
    }
    
    if(flag == true)
        cout << "No";
    else
        cout << "Yes";
    
    return 0;
}

15. 匈牙利算法

模板

时间复杂度是 O(nm)O(nm), nn 表示点数,mm 表示边数

int n1, n2;     // n1表示第一个集合中的点数,n2表示第二个集合中的点数
int h[N], e[M], ne[M], idx;     // 邻接表存储所有边,匈牙利算法中只会用到从第一个集合指向第二个集合的边,所以这里只用存一个方向的边
int match[N];       // 存储第二个集合中的每个点当前匹配的第一个集合中的点是哪个
bool st[N];     // 表示第二个集合中的每个点是否已经被遍历过

bool find(int x)
{
    for (int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true;
            if (match[j] == 0 || find(match[j]))
            {
                match[j] = x;
                return true;
            }
        }
    }

    return false;
}

// 求最大匹配数,依次枚举第一个集合中的每个点能否匹配第二个集合中的点
int res = 0;
for (int i = 1; i <= n1; i ++ )
{
    memset(st, false, sizeof st);
    if (find(i)) res ++ ;
}

二分图的最大匹配 ✔12.29

原题链接

做题总结:
  1. 避免多次重复问一个女生,所以遍历每次男生时,用st存储该男生是否考虑过这个女生,这样其他男生就别再考虑了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/331427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

差分隐私学习笔记

2021网络空间安全西湖学术论坛线上报告中介绍了差分隐私过去发展&#xff0c;目前现状以及未来研究方向。博主对这个报告进行了介绍与总结。总结中提到学习差分隐私最重要的环节是&#xff1a; 了解差分隐私的基本机制&#xff1a;拉普拉斯机制、指数机制和高斯机制差分隐私的组…

【数据结构与算法】前缀树的实现

&#x1f320;作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《数据结构与算法要啸着学》 &#x1f387;座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;…

54 循环神经网络 RNN【动手学深度学习v2】

54 循环神经网络 RNN【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1D64y1z7CA/?spm_id_from333.880.my_history.page.click&vd_source75dce036dc8244310435eaf03de4e330 对序列化数据集的训练网络&#xff0c;通常称为RN…

第三章 Opencv图像像素操作

目录1.像素1-1.确定像素位置1-2.获取指定像素的像素值1-3.修改像素的BGR值2.用numpy模块操作像素2-1.创建图像1.创建黑白图像2.创建彩色图像3.创建随机图像2-2.拼接图像1.水平拼接hstack()方法2.垂直拼接vstack()方法1.像素 1.像素是构成数字图像的最小单位。每一幅图像都是由M…

【第29天】SQL进阶-查询优化- performance_schema系列实战四:查看最近的SQL执行信息(SQL 小虚竹)

回城传送–》《32天SQL筑基》 文章目录零、前言一、 查看最近的top sql1.1 数据准备&#xff08;如果已有数据可跳过此操作&#xff09;1.2 查询events_statements_summary_by_digest表二、查看最近执行失败的SQL2.1 开启第一个会话&#xff0c;执行错误sql2.2 开启第二个会话&…

pytest当中pytest.ini使用

目录 一、作用 二、存放位置 三、功能&#xff08;只列了简单的&#xff09; 1、 addopts 2、更改测试用例收集规则 四、运行就减少了命令了 前言&#xff1a;pytest配置文件可以改变pytest的运行方式&#xff0c;它是一个固定的文件pytest.ini文件。 一、作用 pytest.in…

Ceph分部署存储知识总结

Ceph 一.deploy-ceph部署 投入使用ceph前&#xff0c;要知道一个很现实得问题&#xff0c;ceph对低版本内核得客户端使用非常不友好&#xff0c;低内核是指小于等于3.10.0-862&#xff0c;默认的centos7.5及以下的系统都是小于此类内核&#xff0c;无法正常使用ceph的文件存储…

内网渗透(十一)之内网信息收集-内网IP扫描和发现

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

用YOLOv8推荐的Roboflow工具来训练自己的数据集

YOLOv8是Ultralytics公司开发的YOLO目标检测和图像分割模型的最新版本&#xff0c;相较于之前的版本&#xff0c;YOLOv8可以更快速有效地识别和定位图像中的物体&#xff0c;以及更准确地分类它们。 作为一种深度学习技术&#xff0c;YOLOv8需要大量的训练数据来实现最佳性能。…

如何旋转YUV图片数据且使用Qt显示

前言 提一下这篇文章的需求&#xff1a;将USB相机获取到的YUV数据进行旋转&#xff0c;然后转为QImage进行显示。原本程序中是有旋转的代码&#xff0c;但不知道为什么&#xff0c;旋转出来的图片会花屏。关于花屏的问题&#xff0c;后面会稍微阐述一下。所以&#xff0c;经过…

[多线程进阶] 常见锁策略

专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录: 1. 常见的锁策略 1.1 乐观锁 vs 悲观锁 1.2 读写…

bootstrap 框架

文章目录bootstrap必须使用 HTML5 文档类型排版和链接默认栅格系统带有基本栅格的 HTML 代码媒体类型媒体类型逻辑运算符 用来做条件判断页面布局&#xff1a; 引入 css&#xff08;bootstrap.min.css&#xff09; 类名03-面包屑导航警告框、徽章、面包屑导航、按钮、按钮组卡…

css行内块元素垂直居中

css行内块元素垂直居中 div里边有个img标签&#xff0c;要想让img垂直居中&#xff0c;需要 给父盒子设置line-heightheightimg设置vertical-align:middle <div style"background-color: red; height: 150px;line-height: 150px;"><img src"images/…

Unity开发环境配置

Unity本体安装 1.首先下载安装unityhub,中文管网https://unity.cn/ 2.登录unityhub&#xff0c;选择你想要的版本安装 选择后按照提示选择个人免费试用的license,然后等待unity本体下载安装即可。 VSCode安装和配置 1.去官网https://code.visualstudio.com/下载vscode 2.u…

微信小程序 Springboot ssm房屋租赁系统uniapp设计与实现

房屋租赁系统用户和户主是基于微信端&#xff0c;管理员是基于网页端&#xff0c;系统采用java编程语言&#xff0c;mysql数据库&#xff0c; idea工具开发&#xff0c;本系统分为用户&#xff0c;户主&#xff0c;管理员三个角色&#xff0c;其中用户可以注册登陆小程序&#…

C++11入门

目录 C11简介 统一的列表初始化 {}初始化 std::initializer_list 文档介绍 std::initializer_list的类型 使用场景 initializer_list接口函数模拟实现 auto与decltype nullptr 范围for STL的变化 新容器 新方法 新函数 C11简介 1.在2003年C标准委员会曾经提交了一…

【浅学Redis】缓存 以及 缓存穿透、缓存击穿、缓存雪崩

缓存 以及 缓存击穿、缓存穿透、缓存雪崩1. 缓存1.1 缓存的作用1.2 缓存的应用场景1.3 引入缓存后的执行流程1.4 缓存的优点2. 缓存穿透2.1 场景2.2 解决策略1. 参数校验2. 缓存空值3. 缓存击穿3.1 场景3.2 解决策略4. 缓存雪崩4.1 场景4.2 解决策略5. 上面三者的区别1. 缓存 …

图像分割--入门了解

一. 三种分割 1. 语义分割&#xff08;semantic segmentation&#xff09; 语义分割&#xff1a;语义分割通过对图像中的每个像素进行密集的预测、推断标签来实现细粒度的推理&#xff0c;从而使每个像素都被标记为一个类别&#xff0c;但不区分属于相同类别的不同实例。 比…

ChatGPT之父:世界正被他搅动

阿尔特曼&#xff08;左&#xff09;与马斯克Mac LC2电脑ChatGPT这款聊天应用程序最近太火了&#xff01; 美国北密歇根大学的一名学生用它生成了一篇哲学课小论文&#xff0c;“惊艳”了教授&#xff0c;还得到了全班最高分。美国一项调查显示&#xff0c;53%的学生用它写过论…

Vue (2)

文章目录1. 模板语法1.1 插值语法1.2 指令语法2. 数据绑定3. 穿插 el 和 data 的两种写法4. MVVM 模型1. 模板语法 root 容器中的代码称为 vue 模板 1.1 插值语法 1.2 指令语法 图一 &#xff1a; 简写 &#xff1a; v-bind: 是可以简写成 &#xff1a; 的 总结 &#xff1a; …