染色法判定二分图

二分图染色法

  即可以把所有的点划分到两个集合内,集合内部没有边存在。

一个图是二分图,当且仅当该图中不含奇数环 ——>不含奇数环,那么一定是二分图。有奇数环的话,那么就不能二分图。

判定二分图的依据:若出现一条边的两个端点是同样的颜色(即一个集合的话),那么就不能划分为二分图。

一条边的两个端点一定属于不同的集合。

一个连通块中只要有一个点颜色或集合确定了,那么该连通块中其他所有的点的颜色集合都被确定了。

染色法判定的过程:

for : i 1 - n

  if i未染色

    dfs(i, 1) //把i所在连通块的端点用深搜法全部确定染色

 

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010, M = 2 * N;
int n, m;
int h[N], ne[M], e[M], idx;
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;
    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()
{
    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) puts("Yes");
    else puts("No");
}

注意这里用的染色法color[N], 默认是0,如果!color[i]说明未染色,那么就要dfs(i, 1)进行染色,用邻接表的方式确定下一个该点有边连接的另外一个点,继续dfs(e[i], 3 - c)如果递归返回false,那么不能染,如果该点染色的color[j] == color[u] = c的话,那么也失败了。

注意这里color[i]最好不要用0 和 1, 因为判断有没有染色用的就是!color[i],用0 的话会造成染了和未染混淆。

posted @ 2020-04-16 20:08  龙雪可可  阅读(180)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************