染色法(判断是否为二分图)

O(n+m)

二分图:可以把所有的点划分到两边,使得边只在集合之间,集合内部没有边。

二分图当且仅当图中不含奇数环(边数为奇数条)

// 二分图 - 染色法
#include
#include
using namespace std;

const int N=100010,M=200010;
int n,m;
int h[N],e[N],ne[N],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)
{
	color[u]=c;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(!color[j])
		{
			if(!dfs(j,3-c)) return false;
		}
		else if(color[j]==c) return false;
	}
	return true;
}

int main()
{
	cin>>n>>m;
	memset(h,-1,sizeof h);
	while(m--)
	{
		int a,b;
		cin>>a>>b;
		add(a,b),add(b,a);
	}
	bool flag=true;
	//循环给每个点染色
	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;
}

你可能感兴趣的:(深度优先,算法,图论)