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

news2024/9/25 11:14:09

染色法判定二分图 — 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;
}

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

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

相关文章

C++教程——继承、多态

继承 继承方式 继承中的对象模型 继承中构造和析构顺序 继承中同名成员处理方式 继承中同名静态成员处理方式 多继承语法 菱形继承 虚继承解决资源浪费的问题 底层原理 多态 多态的原理剖析 纯虚函数与抽象类 虚析构与纯虚析构 虚析构

【Linux系统编程】20.程序、进程、CPU和MMU、PCB

目录 程序 进程 CPU和MMU PCB 程序 编译好的二进制文件&#xff0c;存在磁盘上&#xff0c;只占用磁盘资源。 进程 进程是活跃的程序&#xff0c;占用系统资源&#xff0c;在内存中执行。程序运行起来&#xff0c;产生一个进程。 程序类似于剧本&#xff0c;进程类似于一场…

为何OpenAI能领先大厂开发出如ChatGPT的模型

为何OpenAI能领先大厂开发出ChatGPT的大模型&#xff1f; 信仰和环境缺一不可&#xff0c;不是因为OpenAI从0到1创造性的搞出来大模型&#xff0c;而是信仰和环境造就了ChatGPT大模型 在谈论为何中国乃至其他国家的大厂未能开发出如ChatGPT的模型时&#xff0c;我们需要强调&am…

使用electron打包spring-boot+vue项目开发桌面exe端项目一站式全部解决!专栏有解决报错文章

准备工具 前端:node.js 14以下(直接安装 node.js 即可) 后端:jre 1.8(必须1.8) 工具: Bat_To_Exe_ConverterInno_Setup 汉化版(英文版不支持简体中文,打包出来的安装界面是英文的)我以及给大家汇总完毕直接点击进去下载即可 https://pan.baidu.com/s/1XoA0tj3b4Q…

Geoserver静态瓦片服务

愿你出走半生,归来仍是少年&#xff01; 1.静态瓦片服务 此处描述的静态瓦片服务指瓦片本身存储于服务器的磁盘上&#xff0c;常用的服务类型包含了标准TMS服务以及Google的XYZ服务两种类型。 在Geoserver中常用的瓦片服务包含了WMS、WFS、TMS、WTMS等等。在面向数据更新频率不…

【送书福利-第十四期】ChatGPT时代 + PowerBI助力快速创建动态报表

大家好&#xff0c;我是洲洲&#xff0c;欢迎关注&#xff0c;一个爱听周杰伦的程序员。关注公众号【程序员洲洲】即可获得10G学习资料、面试笔记、大厂独家学习体系路线等…还可以加入技术交流群欢迎大家在CSDN后台私信我&#xff01; 本文目录 一、前言二、内容介绍三、抽奖方…

Android 前台服务讲解

目录 Android 前台服务和后台服务区别 前台服务&#xff08;Foreground Service&#xff09;&#xff1a; 后台服务&#xff08;Background Service&#xff09;&#xff1a; 总结&#xff1a; 前台服务更新&#xff1a; JobScheduler、WorkManager 区别和使用方式 andro…

Python encode()函数详解,Python编码解码

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 encode 1、常见编码格式2、返回的是Bytes类型3、错误处理方式4、解码 encode() 可…

5道Mysql面试题

1.什么Mysql的事务&#xff1f;事务的四大特性&#xff1f; Mysql中事务的隔离级别分为四大等级&#xff1a;读未提交&#xff08;READ UNCOMMITTED&#xff09;、读提交 &#xff08;READ COMMITTED&#xff09;、可重复读 &#xff08;REPEATABLE READ&#xff09;、串行化 …

TensorBoard 没有数据

版本 TensorBoard 2.13.0 报错&#xff1a; 打开projector_plugin.py 42行 from tensorboard.compat import notf # noqa: F401 修改为&#xff1a; from tensorboard.compat import tensorflow_stub as tf

Petrozavodsk Winter 2023. Day 1 部分题解

前言&#xff1a;整场的题目质量比较高&#xff0c;虽然之前做过一部分题&#xff0c;但还是被薄纱了 Changing the Sequences 大意&#xff1a; 给定两个数组a,b&#xff0c;长度都为n&#xff0c;元素都介于1-m之间 定义一次操作如下&#xff1a; 构造一个1-m的排列p&…

B - Colorful Stamp

#include<iostream> #include<algorithm> #include<vector> #include<bitset> #include<cmath> #include<set> #include<climits> #include<queue> #include<cstring>//memset头文件 using i64 int64_t; using namespa…

Spring Boot中的会话管理是什么,如何使用

Spring Boot中的会话管理是什么&#xff0c;如何使用 在Web应用程序中&#xff0c;会话是一种存储用户状态信息的机制。Spring Boot提供了会话管理的支持&#xff0c;使得在开发Web应用程序时可以轻松地管理用户的会话信息。本文将介绍Spring Boot中的会话管理是什么以及如何使…

ARM day9 (按键中断控制led亮灭)

key.h #ifndef __KEY_H__ #define __KEY_H__#include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_uart.h" #include "stm32mp1xx_exti.h" #include "stm32mp1xx_gic.h"//事件号 #define EXTI_…

特征选择算法 | Matlab实现基于ReliefF特征选择算法的分类数据特征选择 ReliefF

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 特征选择算法 | Matlab实现基于ReliefF特征选择算法的分类数据特征选择 ReliefF 部分源码 %--------------------

机器学习基础之《特征工程(2)—特征工程介绍、特征抽取》

一、什么是特征工程 机器学习领域的大神Andrew Ng(吴恩达)老师说“Coming up with features is difficult, time-consuming, requires expert knowledge. “Applied machine learning” is basically feature engineering. ” 注&#xff1a;业界广泛流传&#xff1a;数据和特…

看完这篇 教你玩转渗透测试靶机Vulnhub——Hackable: III

Vulnhub靶机hackableII渗透测试详解 Vulnhub靶机介绍&#xff1a;Vulnhub靶机下载&#xff1a;Vulnhub靶机安装&#xff1a;Vulnhub靶机漏洞详解&#xff1a;①&#xff1a;信息收集&#xff1a;②&#xff1a;端口敲门&#xff1a;③&#xff1a;SSH暴力破解&#xff1a;④&am…

java入门概念个人理解之package与import浅析

java入门概念个人理解之package与import浅析 由于近来学习java&#xff0c;遇到了一些在c上没有的概念&#xff0c;将它记http://录下&#xff0c;以自己复习使用&#xff0c;如有不理解妥之处&#xff0c;望大家批评指导。资料均由网上经过自己整合理解而来&#xff0c;如有侵…

Permission denied (publickey,password)问题的解决办法

[15:29:00.146] Terminal shell path: C:\WINDOWS\System32\cmd.exe [15:29:01.703] > root59.110.21.45: Permission denied (publickey,password). 解决&#xff1a; RSA key 登录方法/home/user/ 目录下建立 .ssh/ 文件夹 cd ~/ mkdir .ssh # 注意.ssh文件夹的权限 ch…

STM32+PWM+输入捕获测频

外部时钟&#xff0c;主频64M 定时器1 通道1发出PWM波 频率1K 定时器2 通道1输入捕获&#xff0c;上升沿触发 串口 /* USER CODE BEGIN 0 */ uint32_t time_up_num0;//上升沿计数 float time_frequency;//频率 /* USER CODE END 0 */ 初始换打开定时器 /* USER CODE BEGIN 2 …