染色法判定二分图

205 阅读1分钟

二分图的重要性质:①一定不包含奇数环 ②可能不是连通图
通过染色法判断,环中节点交替被染两种颜色,若产生矛盾,则不是连通图

解题思路

color[i] = {0, 1, 2}i可以被染成两种颜色,1色或2色,0表示未被染色。

  1. 外层循环1 ~ n,由于原图可能不是连通图,所以需要将每个点当作起点做一遍dfs。
  2. color[i] = 0,即未被染色,进行dfs;若已染色不重复运行程序。
  3. dfs(u, i)过程:以u为端点遍历所有邻接边。若另一个端点j未被染色,对其进行染色并再次判断dfs(u, 3 - i);若另一个端点j已染色,则继续判断color[j] == c,若与端点u相同,则说明产生冲突,返回false
  4. 只能染123 - i必然是另一种颜色
  5. 程序正常运行到结束,返回true

C++代码

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

using namespace std;

const int N = 100010, M = 200010;

int n, m;
int h[N], e[M], ne[M], idx;
int color[N];

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

bool dfs(int u, int c)
{
    color[u] = c;

    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!color[j])
        {
            if (!dfs(j, 3 - c))
            {
                return false;
            }
        }
        else
        {
            if (color[j] == c)
            {
                return false;
            }
        }
    }

    return true;
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    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])
        {
            if (!dfs(i, 1))
            {
                flag = false;
                break;
            }
        }
    }

    if (flag)
    {
        cout << "Yes";
    }
    else
    {
        cout << "No";
    }

    return 0;
}