侧边栏壁纸
博主头像
Hope博主等级

努力赚钱的工科研究生

  • 累计撰写 362 篇文章
  • 累计创建 129 个标签
  • 累计收到 5 条评论
标签搜索

染色法

Hope
2022-03-27 / 0 评论 / 0 点赞 / 750 阅读 / 933 字
温馨提示:
本文最后更新于 2022-03-27,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一个挨着一个染色,就是赋值,如果最后出现了矛盾就不是二分图
或者换个说法,一个图如果存在奇数环就一定不是二分图,因为每个点的下一个点与自己不是一个集合,但是依次枚举下去,最后的起点就发生了矛盾。

  • 矛盾: 一个点与他的邻点被赋相同的值,比如一个环中的起点是1,一共7个点,第一个点被赋值a,第二个点被赋值b,第三个点被赋值a...最后第7个点被赋值a,而起点又被赋值b发生了矛盾。

算法流程:

for( i = 1 ~ n){
   if( i 未染色)
   dfs(i ,1) //把i的连通块染色
}
dfs
{
    for(枚举邻点){
        if(没有被染色)
            //染色只有 1 2 所以 3 - 1 = 2, 3 - 2 = 1
            if(!dfs(j,3-u)) return false;
            else if ( 被染色 但颜色和 u 一样 ) return false;
    } 
    return true
}

例题:
Acwing 860. 染色法判定二分图

参考代码:

#include<iostream>
#include<cstring>
using namespace std;

const int N = 1e6+10, M = 2e6+10;
int n,m;
int ne[M],e[M],h[N],idx;
int color[N];

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

bool dfs(int t,int u){
    
    color[t] = u;
    for(int i = h[t];~i;i = ne[i]){
        int j = e[i];
        if(!color[j]){
            if(!dfs(j,3 - u)) return false;
        }
        else if(color[j] == u) return false;
    }
    return true;
}
int main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    
    while(m--){
        int a,b;
        cin>>a>>b;
        add(a,b),add(b,a);
    }
    
    for(int i = 1; i <= n; i++){
        if(!color[i]){
            if(!dfs(i,1)){
                puts("No");
                return 0;
            } 
        }
    }
    puts("Yes");
    return 0;
}
0

评论区