一个挨着一个染色,就是赋值,如果最后出现了矛盾就不是二分图
或者换个说法,一个图如果存在奇数环就一定不是二分图,因为每个点的下一个点与自己不是一个集合,但是依次枚举下去,最后的起点就发生了矛盾。
- 矛盾: 一个点与他的邻点被赋相同的值,比如一个环中的起点是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
}
参考代码:
#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;
}
评论区