【学习笔记】二分图&网络流

二分图

定义

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

判断(染色法)

用黑白两种颜色对图中点染色(将点加入集合),一个点是不能同时有两种颜色的,若有,此图不是二分图

根据染色法,我们发现,二分图内部是绝对不会存在奇环的,不存在奇环的图就是二分图

所以我们对图进行DFS或者BFS,发现奇环就跳出,此图不是二分图

二分图判断
bool dfs(int u,int c){
	color[u]=c;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].to;
		if(color[j]){
			if(color[j]==c){
			return false;
			}
		}
		else if(!dfs(v,3-c)){
			return false;
		}
	}
}
bool check(){
	memset(color,0,sizeof color);
	for(int i=1;i<=n;i++){
		if(color[i]==0){
			if(!dfs(i,1)){
				return false;
			}
		}
	}
	return true;
}

二分图的匹配

给定一个二分图\(G\),\(M\)\(G\)边集的一个子集,如果\(M\)满足当中的任意两条边都不依附于同一个顶点(没有公共端点),则称\(M\)是一个匹配

二分图的最大匹配

图中包含边数最多的匹配称为图的最大匹配

完美匹配

如果所有点都在匹配边上,称这个最大匹配是完美匹配

增广路定理\(Berge'slemma\)

交错路:始于非匹配点且由匹配边与非匹配边交错而成

增广路:是始于非匹配点且终于非匹配点的交错路,路径的长度一定为奇数5

增广路上飞匹配边比匹配边数量多以,如果将匹配边改为未匹配边,未匹配边改为匹配边,则匹配大小会增加一且依然是交错路,匹配数增加的过程,我们称之为增广

增广路(匈牙利)算法\(Augmenting\ Path\ Algorithm\)

核心思想:枚举所有未匹配点,找增广路径,在增广路上关于匹配取反,直到找不到增广路

算法思路:
1.将匹配边集\(M\)置为空
2.找一条增广路径\(P\),\(P\)上的边取反得到一个更大的匹配\(M\)
3.重复上一步直到找不到增广路径为止
算法本质:贪心
实现方法:搜索(递归)
最坏情况会每个点遍历全部边一次,时间复杂度\(O(nm)\)

匈牙利算法
bool find(int x){
	for(int i=1;i<=n;i++){
		if(!st[i]&&g[x][i]){
			st[i]=true;
			int t=match[i];
			if(!t||find(t)){
				match[i]=x;
				return true;
			}
		}
	}
	return false;
}
int main(){
	cin>>n;
	int ans=0;
	for(int i=1;i<=n;i++){
		memset(st,0,sizeof(st));
		if(find(i)){
			ans++;
		}
	}
	cout<<ans;
	return 0;
}

棋盘覆盖

给定⼀个\(N\)\(M\)列的棋盘,已知某些格⼦禁⽌放置。
求最多能往棋盘上放多少块的⻓度为\(2\)宽度为 \(1\)的骨牌,骨牌的边界与格线重合(骨牌占⽤两个格子),并且任意两张骨牌都不重叠。

将棋盘黑白染色,相邻的各自染成不同的颜色,染色后格子分为黑白两类,对应二分图模型中的\(X\)\(Y\)集合

posted @ 2023-10-25 07:13  chancelong  阅读(29)  评论(0编辑  收藏  举报