AcWing 860:染色法判定二分图 ← 染色法 + 二分图

【题目来源】
https://www.acwing.com/problem/content/862/

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

【输入格式】
第一行包含两个整数 n 和 m。
接下来 m 行,每行包含两个整数 u 和 v,表示点 u 和点 v 之间存在一条边。

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

【输入样例】
4 4
1 3
1 4
2 3
2 4​​​​​​​

【输出样例】
Yes

【数据范围】
1≤n,m≤10^5​​​​​​​

【算法分析】
● 二分图的概念:如果无向图 G=(V, E) 的所有点可以分为两个集合 V1,V2,所有边都在 V1 与 V2 之间,且 V1,V2 的内部都没有边,则称 G 是一个二分图。

● 一个图是否为二分图,一般用“染色法”进行判断。染色法的核心思想非常直观:尝试用两种颜色对图中的所有顶点进行着色,并确保‌任何一条边两端的顶点颜色都不相同‌。如果能成功完成着色,则该图是二分图;否则,不是。

● 染色法的染色逻辑
(1)使用两种颜色:颜色 1 和颜色 2。
(2)若当前节点染色为 c,相邻节点必须染为 3^c(即 3-c)。这是因为,3^1=2,3^2=1,故通过异或运算可实现颜色切换。

● 染色法的算法流程通常基于 BFS 或 DFS 实现。
(1)选择一种颜色(如 1)作为起始颜色。
(2)从一个未访问的节点开始,将其染色,然后遍历其所有邻居。
(3)若邻居未染色,则将其染成与当前节点相反的颜色(如 2),并递归(DFS)或入队(BFS)处理。
(4)若邻居已染色,则检查其颜色是否与当前节点相反。若颜色相同,则说明存在奇环,该图不是二分图。

【算法代码】

#include <bits/stdc++.h>
using namespace std;

const int N=1e5+5;
int e[N<<1],ne[N<<1],h[N],idx;
int color[N];
int n,m;

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

//Dye node u with color c
bool dye(int c,int u) {
    color[u]=c;
    for(int i=h[u]; i!=-1; i=ne[i]) {
        int j=e[i];
        if(!color[j]) { //3^1=2,3^2=1
            if(!dye(3^c,j)) return false;
        } else if(color[j]==c) return false;
    }
    return true;
}

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

    bool flag=true;
    for(int i=1; i<=n; i++) {
        if(!color[i]) {
            flag=dye(1,i);
            if(!flag) break;
        }
    }
    if(!flag) cout<<"No\n";
    else cout<<"Yes\n";

    return 0;
}

/*
in:
4 4
1 3
1 4
2 3
2 4

out:
Yes
*/





【参考文献】
https://blog.csdn.net/weixin_51797626/article/details/122650456
https://www.acwing.com/solution/content/175783/
https://www.acwing.com/solution/content/128098/
https://www.acwing.com/solution/content/105874/
https://www.acwing.com/solution/content/246924/

 

posted @ 2025-11-27 22:14  Triwa  阅读(2)  评论(0)    收藏  举报