二分图判定:染色法

二分图判定方法:染色法

\bullet 对于一个二分图的两个集合,假设给同一个集合里的点都染上一样的颜色,那么为了区分这两个集合,就把另一个集合的点染成另外一种颜色。很明显:一条匹配边的两个顶点颜色肯定不一样。

\bullet 对于一个图,判断是不是二分图,就可以用染色法来判定。任意从一个顶点A出发,将它染上色,再找与它相连的顶点B,假设A与B之间的边是匹配边,那么就有两种情况:

1.如果B与A的颜色相同,就代表这个图不是二分图。
2.B还没有染色,就将B染成与A不同的颜色,再找与B相连的顶点,如果遇到1的情况,不是二分图。

1、2这个过程可以用dfs来完成。

\bullet 例题: http://acm.hdu.edu.cn/showproblem.php?pid=4751

\bullet 思路:将单向认识或者互相不认识的两个人之间建双向边,再判定是不是二分图。反证法证明思路的正确性:如果最终确定是一个二分图,那么假设在一个集合中有两个顶点它们不是相互都认识,那么它们就不可能在同一个集合,这个图也不是二分图,证毕。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
const int maxn = 1e3+10;
const int inf = 999999999;
int k,m,n;
int co[maxn],mp[maxn][maxn];

struct node{int to,next;}e[maxn*10];
int head[maxn],cnt = 0;
void add(int s,int E){
    e[ ++ cnt] = {E,head[s]};
    head[s] = cnt;
}
int flag = 0;
bool dfs(int x,int c)
{
    co[x] = c;
    for(int i = head[x];i != -1;i = e[i].next){
        int to = e[i].to;
        if(co[to] == co[x])
            return false;
        if(co[to] == 0 && dfs(to,-c) == false)///如果与x相连的to结点没有染色,并且dfs与to相连的结点遇到了相同的颜色
            return false;
    }
    return true;///两种情况都没有发生返回真
}

void init()
{
    cnt = 0;
    memset(head,-1,sizeof(head));
    memset(e,0,sizeof(e));
    memset(co,0,sizeof(co));
    memset(mp,0,sizeof(mp));
}

void input()
{
    for(int i = 1;i <= n;i++){
        int x;
        while(scanf("%d",&x) && x){
            mp[i][x] = 1;
        }
    }
    for(int i = 1;i <= n;i++){
        for(int j = i + 1;j <= n;j++){
            if(!(mp[i][j] == 1 && mp[j][i] == 1)){
                add(i,j);
                add(j,i);
            }
        }
    }
}
int main()
{
    while(scanf("%d",&n) != EOF){
        init();
        input();
        int flag = 0;
        for(int i = 1 ; i <= n ; i ++ ){
            if(co[i] == 0)
                if(dfs(i,1) == false){
                    flag = 1;
                    break;
                }
        }
        if(flag == 0)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}



发布了34 篇原创文章 · 获赞 7 · 访问量 1882

猜你喜欢

转载自blog.csdn.net/qq_43628761/article/details/97231821
今日推荐