二分图判断

 

 

 

by   GeneralLiu  

 

染色法

 

非常容易写

 

先记录边

遍历节点

如果没有深搜过

那深搜它就是了

并染色

染为 1 和 -1 

如果染色冲突 则 return false

最后 return true

 

代码

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define N 1000
#define M 2000
int col[N],cnt,n,m,head[N],to[M],next[M];
void add(int x,int y){
    next[++cnt]=head[x];
    to[cnt]=y;
    head[x]=cnt;
}
void dfs(int u,int c){
    col[u]=c;
    for(int v,i=head[u];i;i=next[i]){
        v=to[i];
        if(!col[v])
          dfs(v,-c); // 染 -c 
        if(col[v]==col[u]){ // 有冲突 
            printf("NO");
            exit(0);
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int x,y,i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    for(int i=1;i<=n;i++)
        if(!col[i])
            dfs(i,1); // 默认 染色 1 
    printf("YES");
    return 0;
}
View Code

程序主体是球gay最喜欢的dfs  

 

并查集

 

我们可以将每个节点抽象出两个节点 v0,v1.
v0表示v染0这种颜色,v1表示v染1这种颜色。
对于这个新图,
图中的每一条边(iq,jw)(I,j为原本的点编号,q,w为0或1),
表示i选q颜色的话,j一定要选w颜色。

 

上面看懂看不懂的吧

 

直接看代码

可以的!!

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define N 1000
int fa[N<<1],n,m;
int find(int k){return fa[k]==k?k:fa[k]=find(fa[k]);}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n*2;i++)fa[i]=i;
    for(int fx,fy,x,y,i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        
        fx=find(x*2-1);
        fy=find(y*2);
        fa[fx]=fy;//一个染白则另一个染黑 
        
        fx=find(x*2);
        fy=find(y*2-1);
        fa[fx]=fy;//一个染黑则另一个染白 
    }
    for(int i=1;i<=n;i++)
        if(find(i*2)==find(i*2-1)){//既染白又染黑 
            printf("NO");
            return 0;
        }
    printf("YES");
    return 0;
}
View Code

 

posted @ 2017-05-08 19:03  GeneralLiu  阅读(169)  评论(0编辑  收藏  举报