二分图笔记

什么是二分图?

二分图一般针对无向图问题

一张图中,如果能够把全部的点分到两个集合中,保证两个集合内部没有任何边 ,图中的边只存在于两个集合之间,即为二分图


判断二分图

1. 染色法

即用两种颜色对于这张图进行染色,相邻的结点颜色不同,如果没有矛盾,这张图即为二分图。

复杂度O(m+n)

bool dfs(int u,int c) {	//u为当前结点,c为要染的颜色 
	color[u]=c;				//染色
	for (int i=h[u];~i;i=ne[i]){	
		int j=e[i];			//对于这个点连接的所有的点
		if(color[j]) {		//已经被染过色了
			if(color[j]==c) return false;
			//判断,如果两点颜色一样,染色冲突
		}
		else if(!dfs(j,3-c)) return false;
		//否则dfs去染下一个结点,赋予的颜色肯定要跟 c 不一样
	}
	return true;
}

bool check() {
	memset(color,0,sizeof color);		//0 —— 未染色,1 —— 黑色,2 —— 白色
	for(int i=1;i<=n;i++)
		if(color[i]==0)					//一旦某个点没染过色,dfs去染色
			if(!dfs(i,1)) return false;	//如果传回false显然失败,此图不是二分图
	return true;
}

匈牙利算法(求出二分图的最大匹配数):


满足 是二分图 这个前提,才能使用匈牙利算法

最大匹配数:

        两个集合分别选一个点,这两个点之间有边就确认一段关系,最多的关系数量就是这张二分图的最大匹配。
        即在男女的两个集合中,每一对男女,如果之间有边即可确定一条关系,并且只能一夫一妻,看最多能组成多少对夫妻。

复杂度O(nm)

例题:活动 - AcWing 二分图的最大匹配

#include
using namespace std;
const int N=505,M=10010;
int n1,n2,m,match[N],vis[N];	//match保存右侧结点已匹配成功的左侧节点 
vectore[N];
bool find(int x){
	for(int i=0;i

二分图笔记_第1张图片

最小点覆盖:

对于图中的每一条边,都至少有一个顶点在集合中,这个集合即为最小点覆盖。

特别的,在二分图中,最小点覆盖 = 最大匹配数

二分图笔记_第2张图片

 

你可能感兴趣的:(算法,笔记,深度优先,算法,c++,二分图,匈牙利算法)