Loliko_LinawZ

导航

 

给定一个n个点m条边的无向图,图中可能存在重边和自环。

请你判断这个图是否是二分图。

输入格式

第一行包含两个整数n和m。

接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。

输出格式

如果给定图是二分图,则输出“Yes”,否则输出“No”。

数据范围

1n,m1051≤n,m≤105

输入样例:

4 4
1 3
1 4
2 3
2 4

输出样例:

Yes


染色思路
二分图:判断一个图是否二分图主要看这个图有没有奇数环,有奇数环的就不是二分图。
①:给定任意一个点开始染色,假设第一个点染色1,那么这个点的所有连通点都染色2,相对应的,染色2的点的所有连通点都染色为1
②:如果这个图所有点都染色后不会发生矛盾,那么该图就是二分图,否则就不是。

如图所示,这个图染色结束后并无冲突 所以是二分图:

 

 这个图染色以后发生冲突 不是二分图:

 

 

代码详情如下
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010, M = 200010;   //无向边所以M要*2

int n, m;
int h[N], e[M], ne[M], idx;
int color[N];

void add(int a, int b)  //同样用邻接矩阵来存储
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

bool dfs(int u, int c)  //u是当前节点,c是染色点
{
    color[u] = c;   //首先给当前节点染c
    
    for(int i = h[u]; i != -1; i = ne[i])   //从前到后遍历节点
    {
        int j = e[i];   //用j存储当前节点号数
        if(!color[j])   //如果当前节点没有染色
        {
            //把当前节点所连通的点都深搜,
            //然后染上3-c(如果当前是1,连通点应该染3-1=2;如果是2,连通点染3-2=1)
            if(!dfs(j, 3 - c)) return false;    
        }
        //如果当前节点染色了并且和c相同,说明有奇数环
        else if (color[j] == c) return false;
    }
    return true;
}

int main()
{
    scanf("%d%d", &n,&m);
    
    memset(h, -1, sizeof h);
    
    while(m -- )
    {
        int a,b;
        scanf("%d%d", &a, &b);
        add(a,b),add(b,a);
    }
    
    bool flag = true;   //定义一个flag来判断当前图是否有矛盾
    for(int i = 1; i <= n; i ++)    //遍历全部节点
    {
        if(!color[i])   //如果没有染色我们就对它深搜染色
        {
            if(!dfs(i,1))   //如果深搜发现有奇数环,那说明图有矛盾,不是二分图
            {
                flag = false;
                break;
            }
        }
    }
    
    if(flag) puts("Yes");
    else puts("No");
    
    return 0;
}

 




posted on 2020-10-13 16:17  数码暴龙猪  阅读(116)  评论(0编辑  收藏  举报