算法竞赛备考冲刺必刷题(C++) | AcWing 860 染色法判定二分图

本文分享的必刷题目是从蓝桥云课洛谷AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。

欢迎大家订阅我的专栏:算法题解:C++与Python实现

附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总


【题目来源】

860. 染色法判定二分图 - AcWing题库

【题目描述】

给定一个 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

【输入样例】

4 4
1 3
1 4
2 3
2 4

【输出样例】

Yes

【算法标签】

《AcWing 860 染色法判定二分图》 #二分图判定# #染色法#

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

const int N = 100010;     // 定义常量:最大节点数
int n, m;                  // 定义变量:节点数n,边数m
vector<int> G[N];         // 定义邻接表:存储图的边关系
int color[N];             // 定义数组:存储节点的颜色(0未染色,1红色,-1黑色)
bool flag;                // 定义标志:是否为二分图

/**
 * 深度优先搜索进行二分图染色
 * @param x 当前处理的节点
 */
void dfs(int x)
{
    // 遍历当前节点的所有邻接节点
    for (int i = 0; i < G[x].size(); i++) 
    {
        int y = G[x][i];  // 获取邻接节点编号
        
        // 如果当前节点与邻接节点颜色相同,不是二分图
        if (color[x] == color[y]) 
        {
            flag = false;
            return;
        }
        
        // 如果邻接节点未染色,则染相反颜色
        if (color[y] == 0) 
        {
            color[y] = -color[x];  // -1表示黑色
            dfs(y);               // 递归处理邻接节点
        }
    }
}

int main()
{
    cin >> n >> m;  // 输入节点数和边数
    
    // 构建图的邻接表(无向图)
    for (int i = 1; i <= m; i++) 
    {
        int u, v;
        cin >> u >> v;          // 输入边的关系
        G[v].push_back(u);      // 添加双向边
        G[u].push_back(v);
    }
    
    flag = true;  // 初始化标志为真
    
    // 对每个未染色的节点进行染色
    for (int i = 1; i <= n; i++) 
    {
        if (color[i] == 0)     // 如果节点未染色
        {
            color[i] = 1;      // 染成红色(1)
            dfs(i);            // 开始深度优先搜索
        }
    }
    
    // 输出判断结果
    if (flag == true) 
        cout << "Yes";  // 是二分图
    else 
        cout << "No";   // 不是二分图
    
    return 0;           // 程序正常结束
}
//再写一遍
#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

const int N = 100005, M = 200005;  // 定义常量:N为最大节点数,M为最大边数
vector<int> h[N];                  // 定义邻接表:h[i]存储节点i的所有邻接节点
int n, m;                           // 定义变量:节点数n,边数m
int color[N];                       // 定义数组:color[i]表示节点i的颜色(0未染色,1或2表示两种颜色)

/**
 * 深度优先搜索进行二分图染色
 * @param u 当前处理的节点
 * @param c 当前节点要染的颜色(1或2)
 * @return 染色是否成功(是否是二分图)
 */
bool dfs(int u, int c)  
{
    color[u] = c;  // 将当前节点染成c色
    
    // 遍历当前节点的所有邻接节点
    for (int i = 0; i < h[u].size(); i++) 
    {
        int j = h[u][i];  // 获取邻接节点编号
        
        if (color[j] == 0)  // 如果邻接节点未染色
        {
            // 递归尝试将邻接节点染成另一种颜色(3-c)
            if (dfs(j, 3 - c) == false) 
                return false;
        } 
        else if (color[j] == c)  // 如果邻接节点颜色与当前节点相同
        {
            return false;  // 染色失败,不是二分图
        }
    }
    return true;  // 染色成功
}

int main()
{
    cin >> n >> m;  // 输入节点数和边数
    
    // 构建图的邻接表(无向图)
    while (m--) 
    {
        int a, b;
        cin >> a >> b;        // 输入边的关系
        h[a].push_back(b);    // 添加双向边
        h[b].push_back(a);
    }
    
    bool flag = true;  // 初始化标志为真
    
    // 对每个未染色的节点进行染色
    for (int i = 1; i <= n; i++) 
    {
        if (color[i] == 0)     // 如果节点未染色
        {
            // 尝试将节点i染成颜色1,如果失败则不是二分图
            if (dfs(i, 1) == false) 
            {
                flag = false;
                break;
            }
        }
    }
    
    // 输出判断结果
    if (flag) 
        cout << "Yes" << endl;  // 是二分图
    else 
        cout << "No" << endl;   // 不是二分图
    
    return 0;  // 程序正常结束
}

【运行结果】

4 4
1 3
1 4
2 3
2 4
Yes
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值