二分图判定

二分图判定是指给定一个具有 n 个顶点的图,要给图上每个顶点染色,并且要使相邻的顶点颜色不同。问是否能用最多 2 种颜色进行染色?保证图中没有重边和自环。

 把相邻顶点染成不同颜色的问题叫做图的着色问题。对图进行染色所需要的最小颜色数称为最小着色数。最小着色数是 2 的图称作二分图。

例如:

二分图判定_第1张图片

上图显然不是一个二分图,因为三个顶点两两相连,至少需要三种不同颜色;

二分图判定_第2张图片

而这个图显然是一个二分图,只需要满足0、2是一种颜色,1、3是另一种颜色即可。

显然完全图 K_{n} 的最小着色数必为 n(当然只能为 n )。当地 i 个点为第 i 种颜色后,第 i + 1 个点必然不能为前 i 种颜色,因为这 n 个点两两相连,因此共需要 n 种颜色。

二分图判定_第3张图片

如果只用 2 种颜色,那么确定一个顶点的颜色之后,和它相邻的顶点的颜色也就随之确定了。因此,选择从任意一个顶点出发,依次确定相邻顶点的颜色,就可以判断是否可以被 2 种颜色染色了。

这个问题用深度优先搜索容易实现。

#include 
#include 
#include 
#define MAXN 10//定义最大节点数
using namespace std;
vector  G[MAXN];//用邻接表作为图的存储结构
int color[MAXN];//保存每个节点的颜色
int V,E;
void read(){
	for(int i = 0;i < E;i ++){
		int s,t;
		cin >> s >> t;
		G[s].push_back(t);
		G[t].push_back(s);
	}
}
bool dfs(int v,int c){
	color[v] = c;//给节点 v 染色为 c
	//依次对 v 相邻的点进行处理
	for(int i = 0;i < G[v].size();i ++){
		//如果相邻的点和自己颜色相同则则无法达成目标
		if(color[G[v][i]] == c) return false;
		//如果相邻的点没有染色,且对这个点染不同的颜色后,对之相邻顶点的搜索出现矛盾则无法达成目标
		if(color[G[v][i]] == 0 && !dfs(G[v][i],-c)) return false;
	}
	return true;//如果对所有相邻的点都染色成功则返回 true
}
void solve(){//对邻接表中的顶点依次进行搜索染色
	for(int i = 0;i < V;i ++){
		if(color[i] == 0){
			if(!dfs(i,1)){
				cout << "NO" << endl;
				return ;
			}
		}
	}
	cout << "YES" << endl;
}
int main(void)
{
	cin >> V >> E;
	read();
	solve();
	return 0;
}

对于连通图来说,只需要进行 1 次 dfs 即可,而对于非连通图,则需要进行多次 dfs ,这时 solve 函数中的 for 循环便起了作用。事实上,也可以通过这种方法来判断一个图是否为森林。

你可能感兴趣的:(图论)