AcWing 860. 染色法判定二分图

本题链接 :活动 - AcWing

题目:

样例:

输入
4 4
1 3
1 4
2 3
2 4

输出
Yes

思路:

        根据题目意思,我们明确一下二分图的含义。

        二分图是图论中的一个重要概念。一个图被称为二分图,当且仅当能够将其所有顶点分割成两个互不相交的子集,使得每条边的两个顶点分别属于不同的子集。

        换句话说,对于一个二分图,可以把图中的顶点分成两组,使得同一组内的顶点之间没有边相连,而不同组内的顶点之间有边相连。

        通俗的讲,二分图就像是一个人群中的男女混合舞会,所有参与者可以分成两组:男生和女生。在这个舞会上,男生只和女生跳舞,而不和其他男生跳舞;女生也只和男生跳舞,而不和其他女生跳舞。没有两个男生或两个女生会成对跳舞。

        如果一个图是二分图,就意味着可以将所有的点分成两组,使得同一组内的点之间没有直接相连的边,而不同组内的点之间有直接相连的边。这种特性在很多实际问题中都有重要的应用。

        所以,我们可以用DFS或者BFS暴搜即可枚举出答案。

代码详解如下:

DFS法:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define int long long
#define Yes puts("Yes")
#define No puts("No")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;

int n,m;

// 数组模拟链表
vector<int>h(N,-1);	// 链表头指针
int e[N],ne[N],idx;
inline void Add(int a,int b)
{
	e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

int color[N];	// 记录是否染色
// color 状态 0 表示未染色
// 			  1 表示染黑色
// 			  2 表示染白色

bool DFS(int node,int inColor)
{
	color[node] = inColor;	// 将其染色
	
	// 枚举其相连的结点,查看是否染色
	for(int i = h[node];i != -1;i = ne[i])
	{
		int j = e[i];	// 取出相邻的结点
		
		// 如果相邻的结点没有染色
		if(!color[j])
		{
			// 我们将其染成当前结点的另一种颜色,其中如果出现冲突的染色,我们返回 false
			if(!DFS(j,3 - inColor)) return false;
		}else if(inColor == color[j]) return false;
		// 否则,如果相邻的结点已经染色了,并且出现与当前结点的颜色冲突,我们返回 false
	}
	return true;	// 染色没有问题,返回 true
}

inline void solve()
{
	cin >> n >> m;
	while(m--)
	{
		int a,b;
		cin >> a >> b;
		Add(a,b),Add(b,a);	// 由于是无向图,所以双向相连
	}
	
	// 枚举每个结点查看是否染色
	for(int i = 1;i <= n;++i)
	{
		// 如果没有染色,那么我们将其染色
		if(!color[i])
		{
			// 如果出现冲突的染色,直接输出 No
			if(!DFS(i,1))
			{
				No;
				return ;
			}
		}
	}
	Yes;	// 如果都符合二分图定义,输出 Yes
}

signed main()
{
//	freopen("a.txt", "r", stdin);
	IOS;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

BFS法:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define int long long
#define Yes puts("Yes")
#define No puts("No")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;
using PII=pair<int,int>;
int n,m;

// 数组模拟链表
vector<int>h(N,-1);	// 链表头指针
int e[N],ne[N],idx;
inline void Add(int a,int b)
{
	e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

int color[N];	// 记录是否染色
// color 状态 0 表示未染色
// 			  1 表示染黑色
// 			  2 表示染白色

inline bool BFS()
{
	queue<PII>q;	// 存储需染色结点
	
	// 枚举每个结点
	for(int i = 1;i <= n;++i)
	{
		if(!color[i])
		{
			q.emplace(PII(i,1));
			// BFS 搜索
			while(q.size())
			{
				// 取出需染色的结点
				PII now = q.front();	
				q.pop();
				
				// 获取数据
				int node = now.first;
				int inColor = now.second;
				
				color[node] = inColor;	// 开始染色
				
				// 枚举相邻的结点,是否染色
				for(int i = h[node];i != -1;i = ne[i])
				{
					int j = e[i];
					if(!color[j])
					{
						q.emplace(PII(j,3 - inColor));	// 存储染色结点
					}else if(color[j] == inColor) return false;
				}
			}
		}
	}
	return true;
}

inline void solve()
{
	cin >> n >> m;
	while(m--)
	{
		int a,b;
		cin >> a >> b;
		Add(a,b),Add(b,a);	// 由于是无向图,所以双向相连
	}
	
	if(BFS()) Yes;
	else No;
}

signed main()
{
//	freopen("a.txt", "r", stdin);
	IOS;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值