染色法判定二分图 — DFS深搜 +BFS宽搜

2023-10-29

染色法判定二分图 — DFS深搜

题目描述

给定一个 n n n 个点 m m m 条边的无向图,图中可能存在重边和自环。

请你判断这个图是否是二分图。

输入格式

第一行包含两个整数 n n n m m m

接下来 m m m 行,每行包含两个整数 u u u v v v,表示点 u u u 和点 v v v 之间存在一条边。

输出格式

如果给定图是二分图,则输出 Yes,否则输出 No。

数据范围

1 ≤ n , m ≤ 1 0 5 1 \leq n,m \leq 10^5 1n,m105

输入样例:

4 4
1 3
1 4
2 3
2 4

输出样例:

Yes

稀疏图用邻接表存储,因为n和m差不多大所以是稀疏图,如果m远大于n,就算稠密图,n为顶点数,m是边数

在这里插入图片描述

题解

解法1:DFS

首先我们需要了解什么是二分图。二分图,顾名思义,就是可以把图中的节点分成两个集合,使得同一集合内的节点没有边相连。因此,如果给定的图是二分图,也就是说,可以用两种颜色对节点进行染色,使得相邻节点的颜色不同。因此,我们可以使用深度优先搜索(DFS)来实现二分图的判断。

具体来说,我们可以从任意一个节点开始,将其染成红色,并遍历与其相邻的节点,将这些节点染成蓝色。接下来,对于每个蓝色的节点,再遍历与其相邻的节点,将这些节点染成红色。重复以上操作,直到所有的节点都被染色。如果染色过程中出现了相邻节点颜色相同的情况,则说明给定的图不是二分图。

具体实现时,我们可以使用一个颜色数组 c o l o r color color,用来记录每个节点的颜色。初始时,所有节点的颜色都是未染色的(可以用 − 1 -1 1 表示)。在 DFS 过程中,对于当前遍历到的节点 u u u,如果它没有被染色,则将其染成与其相邻节点的颜色相反的颜色,并继续遍历与其相邻的未染色节点;如果它已经被染色,并且颜色与与其相邻节点的颜色相同,则说明给定的图不是二分图。最终,如果所有的节点都被染色了,并且没有相邻节点颜色相同的情况出现,则说明给定的图是二分图。

时间复杂度:

DFS 的时间复杂度为 O ( n + m ) O(n+m) O(n+m),其中 n n n 表示节点数目, m m m 表示边数目。

#include<iostream>
#include<cstring>
using namespace std;
const int N = 2e5+10;
int h[N], e[N], ne[N], idx;
int n,m;
int color[N];

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

bool dfs(int u,int c){
    color[u] = c;//将点u染色为c
    for(int i = h[u];i!=-1;i = ne[i]){//继续染色它的子结点
        int j = e[i];//子结点编号
        if(!color[j]){//如果子结点j未被染色,就将它染为与父结点不同的颜色
            if(!dfs(j,3 - c)){//染色过程出现冲突
                return false;
            }
        }else if(color[j] == c){//子结点颜色相同
            return false;
        }
    }
    return true;

}

int main(){
    cin>>n>>m;
    int u,v;
    memset(h,-1,sizeof h);
    while(m--){
        cin>>u>>v;
        add(u,v),add(v,u);
    }

    for(int i = 1;i<=n;i++)//可能存在非连通图
    if(!color[i])
        if(!dfs(i,1)){
            cout<<"No";
            return 0;
        }
    cout<<"Yes";
    return 0;
}


解法2:BFS

除了 DFS,我们还可以使用广度优先搜索(BFS)来实现二分图的判断。

具体来说,我们可以从任意一个节点开始,将其染成红色,并将其入队列。接下来,每次从队列中取出一个节点 u u u,遍历与其相邻的节点 v v v。如果 v v v 没有被染色,则将其染成与 u u u 相反的颜色,并将其入队列;如果 v v v 已经被染色,并且颜色与 u u u 相同,则说明给定的图不是二分图。

具体实现时,我们可以使用一个颜色数组 c o l o r color color,用来记录每个节点的颜色。初始时,所有节点的颜色都是未染色的(可以用 − 1 -1 1 表示)。在 BFS 过程中,对于当前遍历到的节点 u u u,如果它没有被染色,则将其染成与其相邻节点的颜色相反的颜色,并将其入队列;如果它已经被染色,并且颜色与与其相邻节点的颜色相同,则说明给定的图不是二分图。最终,如果所有的节点都被染色了,并且没有相邻节点颜色相同的情况出现,则说明给定的图是二分图。

时间复杂度:

BFS 的时间复杂度为 O ( n + m ) O(n+m) O(n+m),其中 n n n 表示节点数目, m m m 表示边数目。

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

using namespace std;

const int N = 100010, M = 2 * N;

int h[N], e[M], ne[M], idx;
int color[N]; // 用来记录每个节点的颜色,-1 表示未染色,0 表示染成红色,1 表示染成蓝色

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

bool bfs(int u)
{
    queue<int> q;
    q.push(u);
    color[u] = 0;

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

        for (int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if (color[j] == -1)
            {
                color[j] = !color[t];
                q.push(j);
            }
            else if (color[j] == color[t])
                return false;
        }
    }

    return true;
}

int main()
{
    memset(h, -1, sizeof h);

    int n, m;
    cin >> n >> m;

    while (m -- )
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
    }

    bool flag = true;
    memset(color, -1, sizeof color);
    for (int i = 1; i <= n; i ++ )
        if (color[i] == -1)
            if (!bfs(i))
            {
                flag = false;
                break;
            }

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

    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

染色法判定二分图 — DFS深搜 +BFS宽搜 的相关文章

随机推荐

  • 研发工具链介绍

    本节课程为 研发工具链介绍 我们将主要学习三个工具 项目管理工具 iCafe 代码管理工具 iCode 交付平台 iPipe 此外我们知道 管理实践具有以下三个特点 用 精益 指引产品规划 用 敏捷 加速迭代开发 用 数据 驱动持续改进 而
  • 那些在一个公司死磕5年以上的测试,最后都怎么样了?

    2023年的测试市场是崩溃的 即使是老员工 也要面对裁员 降薪 外包化 没前途 薪资不过20k 没有面试 找不到工作 确实都客观存在 但与此同时 也有不少卷赢同行拿高薪的案例 因为只要互联网存在 测试就是刚需 只是需要更卷一些了 这里我准备
  • MSRA实习申请经验分享

    MSRA实习申请经验分享 自我介绍 简历投递 面试 成败关键点 自我介绍 博主目前大四 因为大四下没啥事想申请到MSRA实习半年 不久前成功申请到了MSRA的实习 这里简单分享一下经验 首先自我介绍一下 本人本科是国内某top10的985高
  • springboot简单整合logback日志框架

    引入依赖 实际上我们只需要引入springboot的的web依赖就可以了 springboot是默认整合logback的依赖的 编写xml文件 xml文件默认叫做logback xml 放在resource目录下就可以
  • python画桃心表白

    python用turtle画简单图案比较方便 大一学python的turtle模块时 记得要画各种图案 如国旗 桃心等等图案 期末课程设计时有可能还会遇到画54张扑克牌 当初室友就被迫选了这道题 下面是程序 import turtle im
  • 基于FREERTOS系统的LWIP协议移植(STM32F1战舰版)

    文章目录 参考文献 前言 源码链接 FREERTOS系统介绍 FREERTOS系统之API函数 1 创建任务函数xTaskCreate 2 删除任务函数xTaskDelete 3 创建二值信号量函数xSemaphoreCreateBinar
  • 找不到BufferedImage这个Class的解决方法

    找不到BufferedImage这个Class的解决方法 环境 1 RedHat AS5 64位 2 WebSphere6 0 32位版本 正文 发现原来在RedHat AS4 32位系统上跑的程序不能在64位RedHat AS5中运行 系
  • 你还在 Docker 中跑 MySQL?恭喜你,好下岗了!

    上一篇 一个90后员工猝死的全过程 0 2T架构师学习资料干货分享 来源 toutiao com i6675622107390411276 容器的定义 容器是为了解决 在切换运行环境时 如何保证软件能够正常运行 这一问题 目前 容器和 Do
  • PyTorch 入坑七:模块与nn.Module学习

    PyTorch 入坑七 模型创建概述 PyTorch中的模块 torch模块 torch Tensor模块 torch sparse模块 torch cuda模块 torch nn模块 torch nn Parameter torch nn
  • 电脑开机不启动原因

    现象 长时间不关机 息屏后无法唤醒 电源指示灯亮 但是是黑屏 拔电重开 还是黑屏 显示器提示进入节电模 首先怀疑是内存条松了 或者接触不良 本人机器这边解决步骤如下 1 拔插内存条 开机试试 2 内存条换位置 开机试试 3 先取下一条内存条
  • conda install 和 pip install的区别

    目录 前言 一 范围不同 二 使用条件不同 三 对虚拟环境的管理能力不同 四 可使用包的数量不同 前言 conda和pip一般被认为是几乎相同的 但这两个工具虽然功能存在部分重叠 但其设计的目的是不同的 一 范围不同 Anaconda是一个
  • PCA、聚类、LFDA 和 MDS 相关绘图 iris (R语言)

    本文档使用 ggplot2 和解释了 PCA 聚类 LFDA 和 MDS 相关绘图 ggfortify 绘制 PCA 主成分分析 ggfortify 让我们 ggplot2 知道如何解释 PCA 对象 加载后 ggfortify 您可以gg
  • SpringBoot2的异常处理、Aop(事务)、拦截器

    目录 一 异常处理 一 ControllerAdvice ExceptionHandler 注解处理异常 二 自定义 HandlerExceptionResolver 类处理异常 二 事务Aop的相关使用 主要说明事务的使用方式 一 事务的
  • 项目安全问题-SM4加解密

    本篇建议与下方链接文章一起观看 http t csdn cn tjmeS 项目安全问题一直被人们研究 当前端路径上通过 status这种拼接参数时 参数的值在浏览器路径栏上非常醒目 是很容易被人恶意修改的 比如该用户并没有编辑权限 但有心之
  • 启动tomcat 服务报 The file is absent or does not have execute permission

    原因 部分文件没有可以执行的权限 1 在linu上部署好tomcat后 准备启动时报错 Cannot find bin catalina sh The file is absent or does not have execute perm
  • Linux自动化运维工具ansible详解

    文章目录 认识ansible ansible的组成 ansible的相关文件 ansible的使用 ansible的常用模块 1 copy模块 2 fetch模块 3 command模块 4 shell 模块 5 file模块 6 cron
  • 域用户访问samba共享提示“指定的网络密码不正确”

    samba默认工作组为WORKGROUP 导致windows无法访问 提示 指定的网络密码不正确 为了解决这个问题 只需要删除注册表中的一项就可以了 win r 输入regedit 回车 找到HKEY LOCAL MACHINE SYSTE
  • 单片机基础

    今天 我给大家更新一个新的模块 单片机 单片机是一个将运算单元 ALU 控制单元 寄存器组 存储器 ROM RAM I O接口 系统总线 定时 计数器集成一起 是一种集成电路芯片 在一块集成电路芯片上 集成了CPU ROM RAM I O接
  • 扯一扯HTTPS单向认证、双向认证、抓包原理、反抓包策略

    HTTP HyperText Transfer Protocol 超文本传输协议 被用于在Web浏览器和网站服务器之间传递信息 在TCP IP中处于应用层 这里提一下TCP IP的分层共分为四层 应用层 传输层 网络层 数据链路层 分层的目
  • 染色法判定二分图 — DFS深搜 +BFS宽搜

    染色法判定二分图 DFS深搜 题目描述 给定一个 n n n 个点 m m m 条边的无向图 图中可能存在重边和自环 请你判断这个图是否是二分图 输入格式 第一行包含两个整数