D24【模板】二分图判定 染色法

D24【模板】二分图判定 染色法_哔哩哔哩_bilibili

 

如果一张无向图的 N 个节点可以分成 A,B 两个不相交的非空集合,并且同一集合内的点之间没有边相连,称该无向图为二分图

定理:二分图不存在奇环(长度为奇数的环)或 二分图是可 2‑着色的

因为每一条边都是从一个集合走到另一个集合,只有走偶数次才可能回到同一个集合。左图是,右图不是

染色法判定二分图

当一个点被标记颜色 1 后,与它相邻的点都标记颜色 2,若标记过程产生冲突,则说明图中存在奇环

树、偶环、网格图等都是常见的二分图的例子

很多图论优化问题都可以在二分图上高效解决

  • 极大团(平凡)
  • 最小点着色(平凡)
  • 最小边着色
  • 最大匹配
  • 最小边覆盖
  • 最小点覆盖
  • 最大独立集
  • 最大权匹配
  • 二分图博弈

参考:二分图 - OI Wiki

 

U169194 【模板】二分图判定 - 洛谷          U248878 染色法判定二分图 - 洛谷   

// 染色法判定二分图 O(n+m)
#include<bits/stdc++.h>
using namespace std;

const int N=1005,M=2000005;
int to[M],ne[M],h[N],idx;
void add(int a,int b){
  to[++idx]=b; ne[idx]=h[a]; h[a]=idx;
}
int n,m,color[N]; //color[u]=0,1,2

bool dfs(int u,int c){ //u点,u的颜色
  color[u]=c;
  for(int i=h[u];i;i=ne[i]){
    int v=to[i];
    if(!color[v]){ //若v未染色
      if(dfs(v,3-c)) return 1; //搜索v,给v染不同色,若有奇环则返回1
    }
    else if(color[v]==c) return 1; //若v已染色且与u同色,说明有奇环则返回1
  }
  return 0; //已搜完u的邻点没有奇环,则返回0
}
int main(){
  int T; cin>>T;
  for(int i=1;i<=T;i++){
    memset(h,0,sizeof h); idx=0;
    memset(color,0,sizeof color);
    cin>>n>>m;
    for(int i=0,a,b;i<m;i++){
      cin>>a>>b;add(a,b);add(b,a);
    }
    
    bool ok=true; //是二分图
    for(int i=1;i<=n;i++)if(!color[i])if(dfs(i,1)){ //有奇环
      ok=false; break;
    }
    if(ok) printf("case %d: \nYes\n",i);
    else printf("case %d: \nNo\n",i);
  }
  return 0;
}

 

posted @ 2022-06-28 08:04  董晓  阅读(1355)  评论(0)    收藏  举报