算法刷题笔记 染色法判定二分图(染色法例题 C++实现)

文章目录

题目描述

  • 给定一个n个点m条边的无向图,图中可能存在重边和自环。
  • 请你判断这个图是否是二分图。

输入格式

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

输出格式

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

数据范围

  • 1 ≤ n,m ≤ 10^5

二分图介绍和基本思路

  • 二分图的定义:一种特殊的无向图,其顶点集可以划分为两个不相交的子集,使得每一条边都恰好连接两个子集中的顶点,即每一条边都是跨集合的。
  • 二分图判定定理:一个图是二分图当且仅当图中不含有边数为奇数的环。
  • 染色法判定二分图的思想:在深度优先搜索(DFS)的过程中对图中的顶点进行染色,如果染色的过程中任何两个相邻的顶点被染成了相同的颜色,则这个图就不是二分图,否则该图就是二分图。

实现代码(C++)

cpp 复制代码
#include <cstdio>
#include <vector>
using namespace std;

// 【辅助常量定义】无向图中的点个数上限
const int N = 100010;

// 【变量定义】无向图中点的个数和边的条数
int n, m;
// 【变量定义】无向边的两个端点的编号
int u, v;
// 【变量定义】用于存储无向边信息的邻接表
vector<int> edges[N];
// 【变量定义】用于记录二分图判定的结果
bool result;
// 【变量定义】用于记录哪些点被染色了(初始所有元素都为0,表示所有点都未被染色)
int colored[N];

// 【函数定义】用于给无向图中指定编号的点和与其可以连接的点进行染色的函数
bool coloring(int number, int color)
{
    // 【判定阶段】如果该点没有进行染色,则对其以及与其相连的点进行染色
    if(colored[number] == 0) 
    {
        // 首先对该点进行染色
        colored[number] = color;
        // 对与该点相连的顶点进行染色(当前顶点是颜色1则染颜色2,否则染颜色1)
        for(int node : edges[number]) 
        {
            if(coloring(node, 3 - color) == false) return false;
        }
        // 判定可以染色
        return true;
    }
    // 如果该点已经完成了染色,则判定其染色结果与本次待染的颜色是否矛盾,如果矛盾则返回false
    else
    {
        if(colored[number] != color) return false;
    }
}

// 【函数定义】用于判定一张无向图是否是二分图的函数
bool judge_graph(void)
{
    // 【点的遍历】顺序遍历无向图中的每一个点,并对该点所有连接的点进行染色(染第一种颜色)
    for(int i = 1; i <= n; ++ i)
    {
        // 【判定阶段】如果当前点还没有进行染色,则对该点以及与该点连接的点进行染色
        // 如果染色过程中发生矛盾,则输出结果
        if(colored[i] == 0) if(coloring(i, 1) == false) return false;
    }
    // 如果成功完成了对无向图中所有点的染色,则说明该图是二分图
    return true;
}

int main(void)
{
    // 【变量输入】输入无向图中点的个数和边的条数
    scanf("%d%d", &n, &m);
    // 【变量输入】输入无向图中的每一条边
    for(int i = 0; i < m; ++ i)
    {
        scanf("%d%d", &u, &v);
        // 使用邻接表来存储无向边的信息
        edges[u].push_back(v);
        edges[v].push_back(u);
    }
    // 【获取结果】使用自定义的函数判定该无向图是否是二分图
    result = judge_graph();
    // 【结果输出】根据结果输出该无向图是否是二分图
    if(result == true) printf("Yes");
    else printf("No");
    
    return 0;
}
相关推荐
沐雪轻挽萤8 分钟前
1. C++17新特性-序章
java·c++·算法
雾喔12 分钟前
【学习笔记2】快速上手调用 AI API & Prompt Engineering
人工智能·笔记·学习
郝学胜-神的一滴17 分钟前
从链表到二叉树:树形结构的入门与核心性质解析
数据结构·c++·python·算法·链表
csdn_aspnet23 分钟前
C语言 (QuickSort using Random Pivoting)使用随机枢轴的快速排序
c语言·算法·排序算法
玖釉-23 分钟前
深入解析 meshoptimizer:基于 meshopt_computeSphereBounds 的层级包围球构建与 DAG 优化
c++·算法·图形渲染
CoderMeijun25 分钟前
C++ 单例模式:饿汉模式与懒汉模式
c++·单例模式·设计模式·饿汉模式·懒汉模式
电商API&Tina32 分钟前
淘宝 / 京东关键词搜索 API 接入与实战用途教程|从 0 到 1 搭建电商选品 / 比价 / 爬虫替代系统
java·开发语言·数据库·c++·python·spring
语戚42 分钟前
力扣 494. 目标和 —— 回溯 & 动态规划双解法全解(Java 实现)
java·算法·leetcode·动态规划·力扣·dp·回溯
初圣魔门首席弟子1 小时前
Doxygen 文档注释详细介绍(含实际案例)
c++
北顾笙9801 小时前
day23-数据结构力扣
数据结构·算法·leetcode