• acwing 860. 染色法判定二分图(dfs,bfs)


    题目传送门

    题目描述

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

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

    输入格式

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

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

    输出格式

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

    数据范围

    1≤n,m≤10^5

    输入样例:

    4 4
    1 3
    1 4
    2 3
    2 4
    

    输出样例:

    Yes
    

    二分图判定

    分析

    二分图定义:

    • 将图中的点分成两组,使得所有边都是在两组之间的

    性质:

    • 一个图是二分图当且仅当 这个图不含有奇数环(有奇数条边的环)
    • 如果图中不含奇数环,那么染色过程中没有矛盾

    染色法判断是不是二分图(dfs)

    • 对每个没染色的点u dfs
      • 首先将该点染成1
      • 然后对其邻接的所有点v遍历
        • 如果v没有染色,将其染成 3 - color[u]
        • 如果这个点v已经被染色了,则判断u,v颜色是不是相同,相同说明矛盾,返回false

    代码

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N = 1e5 + 0;
    const int M = N << 1;
    
    int color[N]; // 1表示黑,2表示红
    int h[N], e[M], ne[M], idx = 0;
    int n,m;
    
    void add(int a, int b)
    {
    	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
    }
    
    bool dfs(int u, int c)
    {
    	color[u] = c;
    	
    	// 染色 
    	for(int i = h[u]; i != -1; i = ne[i])
    	{
    		int j = e[i];
    		if(!color[j])
    		{
    			bool t = dfs(j, 3 - c);
    			if(!t) return false;
    		}
    		else
    		{
    			if(color[j] == c) return false;	
    		} 
    	}
    	return true;
    }
    
    bool bfs(int u)
    {
    	queue<int> q;
    	if(!color[u]) color[u] = 1; // 从u开始bfs 
    	q.push(u);
    	
    	while(q.size())
    	{
    		int t = q.front();
    		q.pop();
    		
    		for(int i = h[t]; ~i; i = ne[i])
    		{
    			int j = e[i];	
    			// if(st[j]) continue;
    			
    			// 没染色就对他染色 
    			if(!color[j])
    			{
    				color[j] = 3 - color[t];
    				q.push(j);
    			}
    			else
    			{
    				if(color[j] == color[t]) return false;
    			}
    		}
    	}
    	return true;
    }
    
    int main()
    {
    	memset(h, -1, sizeof(h));
    	scanf("%d%d", &n, &m);
    	for(int i = 0; i < m; i++)
    	{
    		int a, b;
    		scanf("%d%d", &a, &b);
    		add(a, b), add(b, a); // 无向图 
    	}
    	
    	bool flag = true;
    /*
    	for(int i = 1; i <= n; i++)
    	{
    		if(!color[i])
    		{
    			bool t = dfs(i, 1); 
    			if(!t) 
    			{
    				flag = false;
    				break;	
    			}	
    		}	
    	}
    */ 
    	for(int i = 1; i <= n; i++)
    	{
    		if(!color[i])
    		{
    			if(!bfs(i))
    			{
    				flag = false;
    				break;
    			}
    		}
    	}
    	
    	if(flag) puts("Yes");
    	else 	 puts("No");
    	return 0; 
    } 
    

    时间复杂度

    参考文章

    https://www.acwing.com/solution/content/42481/

    https://www.acwing.com/solution/content/5281/

  • 相关阅读:
    CODE[VS] 2506 可恶的体育老师
    CODE[VS] 3411 洪水
    CODE[VS] 2692 小明过生日
    CODE[VS] 2291 糖果堆
    CODE[VS] 2008 你已经爱我多久了
    忽然之间
    Amazing grace 奇异恩典
    无处安放
    AC日记
    AC日记
  • 原文地址:https://www.cnblogs.com/VanHa0101/p/16017914.html
Copyright © 2020-2023  润新知