二分图学习笔记

如果一张无向图的 \(N\) 个节点 \((N\ge 2)\) 可以分成 \(A,B\) 两个费控集合,其中 \(A\cap B=\varnothing\),并且在同一集合的的点之间都没有边相连,那么称这张图为二分图\(A,B\) 分别被称为二分图的左部和右部。


二分图的判定

定理:一张图是二分图,当且仅当图中不存在奇环。(证明略,感性理解一下qwq)

时间复杂度为 \(O(N+M)\)

bool dfs(int x,int mid,int col)//若是二分图返回true
{
	c[x]=col;
	for(int i=lk[x];i;i=nxt[i])
	{
		int y=to[i];
		if(val[i]<=mid)continue;
		if(!c[y]&&!dfs(y,mid,3-col))return false;
		else if(c[y]==c[x])
		{
			return false;
		}
	}
	return true;
}
例题:关押罪犯

\(N\) 名罪犯,编号从 \(1\)\(N\),共有 \(2\) 座监狱,给出 \(M\) 对关系,表示把罪犯 \(x\) 和罪犯 \(y\) 安排在同一所监狱的代价为 \(c\),求出安排使得所有代价最大值(不是求和)的最小值。

分析:最大值的最小值,可以想到二分。我们设每次二分需要对当前的 mid 检验是否能让超过 mid 的关系不发生在同一座监狱中,所以转化为大于 mid 的关系连边,判断当前图是否为二分图。


二分图最大匹配

任意两条边没有公共端点的边集成为二分图的匹配。在二分图中包含最多边的一组匹配成为二分图的最大匹配

对于一组匹配 \(S\),属于 \(S\) 的边被称为匹配边,其余为非匹配边。匹配边的端点被称为匹配点,其它节点被称为非匹配点。如果在二分图中存在一条连接两个非匹配点的路径 \(path\),使得匹配边和非匹配边在路径上交错出现,那么称 \(path\) 是匹配 \(S\)增广路,也称交错路

增广路显然具有性质:

  1. 长度为奇数;
  2. 路径上第奇数条边为非匹配边,其余为匹配边.

由于以上性质,我们显然可以把路径上所有路径取反,得到一组新的匹配,并且匹配边数加一。太好了!

进一步得到推论:二分图的一组匹配 \(S\) 是最大匹配,当且仅当图中不存在 \(S\) 的增广路。

匈牙利算法(增广路算法)

用于计算二分图的最大匹配。主要过程为:

  1. \(S=\varnothing\)
  2. 寻找增广路 \(path\) 把路径上所有匹配状态取反,得到一个更大的匹配 \(S'\)
  3. 重复第二个步骤,直到图中不存在增广路。

算法的关键在于如何寻找增广路。匈牙利算法依次尝试给每一个左部节点 \(x\) 寻找一个可以匹配的右部节点 $y。两个节点可以匹配时,需要满足以下两个条件之一:

  1. \(y\) 本身为非匹配点。
  2. \(y\) 已经与左部点 \(x'\) 匹配,但是从 \(x'\) 出发能够找到另一个与之匹配的点 \(y'\)。此时 \(x\to y\to x'\to y'\)为一条增广路。

整体复杂度为 \(O(NM)\)我们发现循环的时候只需要遍历左部节点,那么一般情况下此代码求出的 \(ans\) 需要除以 \(2\)

bool dfs(int x)//若能找到增广路,返回true
{
	for(int i=lk[x];i;i=nxt[i])
	{
		int y=to[i];
		if(vis[y])continue;
		vis[y]=true;
		if(!match[y]||dfs(match[y]))
		{
			match[y]=x;return true;
		}
	}
	return false;
}

二分图匹配的模型有两个要素:

  1. “ 0 要素”:节点可以分成两个内部有 0 条边的集合;
  2. “ 1 要素”:每个节点只能与一条匹配边相连。
例题:棋盘覆盖

给定一个 \(N\times M\) 的棋盘,有 \(K\) 个禁止放置的位置,问最多能放多少块 \(1\times 2\) 的骨牌。

分析:本题中的 “1” 为每个格子只能被一块骨牌覆盖。如果把棋盘按照“黑白黑白\n白黑白黑”的方式染色,显然同色的格子之间是没有连边的。要让骨牌在不重叠的情况下尽量多放,就是求以每个格子为节点,相邻格子代表的节点之间连边的二分图的最大匹配数。

二分图最大匹配的必须边与可行边

对于完备匹配,求出最大匹配后,我们把匹配边从右向左连有向边,对于非匹配边,从左向右连边。如果一条边是匹配边而且端点不在同一个强联通分量中,则是必须边;若一条边是匹配边或者端点在同一个强联通分量中,为可行边。

例题:Sorting Slides

显然是完备匹配,只需求二分图最大匹配的必须边。


完备匹配

给定一张二分图,左右两边均为 \(N\) 个节点,如果该二分图的最大匹配包含 \(N\) 条匹配边,称该二分图具有完备匹配。


多重匹配

给定一张包含 \(N\) 个左部节点,\(M\) 个右部节点的无向图。从中选择尽量多的边,使第 \(i(1\le i\le N)\) 个左部节点至多与 \(kl_i\) 条选出的边相连,第 \(j(1\le j\le M)\) 个右部节点至多与 \(kr_j\) 条选出的边相连。这就是二分图的多重匹配问题。
此问题一般有四种解决方案:

  1. 拆点。
  2. 如果只有左侧是多重匹配,可以直接让每个左侧的节点执行 \(kl_i\) 次 dfs。
  3. 如果只有右侧是多重匹配,让右部节点可以匹配 \(kr_j\) 次,超过匹配次数后,依次递归尝试当前匹配的 \(kr_j\) 个左部节点,看是否能找到增广路。
  4. 网络流。最高效的解决方法orz。
例题:Steady Cow Assignment

\(N\) 头牛和 \(B\) 座房子,每头牛对这些房子有一个喜好排列,每座房子有一个最大容纳量,在房子能容纳下的情况下,问怎样安排可以使每头牛属于的房子在各自的房子喜好排列中的下标的最大值和最小值的差值 \(+1\) 最小。(大概就是这个意思)

分析:“0”是显然的,“1”是每头牛只能属于一座房子。但是一座房子可以容纳多头牛,考虑拆点,这样依然可以保证拆点后的图依然是一一匹配。虽然 \(N,B\) 都很小但并不是乱搞就能过,需要剪枝。


二分图带权匹配

有两种解法:费用流和KM算法。在稠密图上,KM算法的效率高于费用流,代码实现也更加简单。不过KM算法也有很大的局限性,只能满足在“带权最大匹配一定是完备匹配”的图中正确求解。

交错树

在匈牙利算法中,如果从某个左部节点出发寻找匹配失败,那么在 dfs 的过程中,所有访问过的节点以及经过的边构成一棵树,这棵树的根节点和叶子结点都是左部点,第奇数层的边是非匹配边,偶数层的边是匹配边。因此,这棵树被称作交错树

顶标

即“顶点标记值”。二分图中,给每个左部节点一个整数值 \(A_i\),给每个右部节点一个 \(B_j\),同时必须满足 \(\forall i,j ,A_i+B_j\ge w(i,j)\)。这些整数值称为节点的顶标

相等子图

二分图中所有节点和满足 \(A_i+B_j=w(i,j)\)的边构成的子图,称为二分图的相等子图

定理:若相等子图中存在完备匹配,则这个完备匹配就是二分图的带权最大匹配。


二分图的最小点覆盖

给定一张二分图,求出一个最小的点集 \(S\),使得图中任意一条边都有至少一个端点属于 \(S\)。这个问题被称为二分图的最小点覆盖。

\(K\ddot{o}nig\) 定理

二分图最小点覆盖包含的点数等于二分图最大匹配包含的边数。

二分图最小点覆盖的构造方法如下:

  1. 求出二分图的最大匹配;
  2. 从左部每个非匹配点出发,再执行一次 dfs 寻找增广路的过程,标记访问过的节点;
  3. 左部未被标记的点和右部被标记过的点,就得到了二分图的最小点覆盖。
    正确性证明略。
例题:Machine Schedule

给出 \(N\) 个任务,每个任务可以选择用机器 \(A\) 在模式 \(a_i\) 下完成,或者用机器 \(B\) 在模式 \(b_i\) 下完成,完成的顺序任意。问最少转换模式多少次可以完成所有任务。

分析:“0”依然是显然的,“1”是每个任务只能被一个机器完成,二分图最小覆盖模型还有一个“2”要素:每条边的两个端点至少选择一个。这里就是每个任务至少要选择一个机器来完成。把每个任务视作一条边,每种模式视作一个节点,求出二分图的最小覆盖就是答案。这个初始状态为 \(0\) 太坑了!


二分图最大独立集

定理:

  1. 无向图的最大团等于其补图的最大独立集。
  2. 二分图的最大独立集的大小等于点的数量减去最大匹配数。
例题:骑士放置

一个 \(N\times M\) 的棋盘上,给定 \(K\) 个无法放置的位置,问最多能放多少个无法相互攻击的骑士。骑士可以攻击“日”字型对角线的棋子。

分析:显然两个可以攻击到的棋子在按照上一道棋盘的题的染色方式染色后会属于两个不同的颜色集合,再在这样的两个节点之间连边,求出此图的最大独立集即可。

也可以用最小覆盖来看此题。把每个格子的初始状态想成有棋子,如果几个节点的共同可以攻击的位置上是空的(对应一个选中的节点覆盖了若干条边),这几个位置就算到了(大概就是这个意思)。算出二分图的最小覆盖为 \(cnt\),答案为 \(N\times M-cnt-K\)


有向无环图的最小路径点覆盖

给定一张有向无环图,要求用尽量少的不相交的简单路径覆盖所有顶点,这个问题被称为有向无环图的最小路径点覆盖。

我们把原来有向图中的每条边 \((x,y)\) 拆成新图中的无向边 \((x,y+N)\) (或许你喜欢 x<<1,y<<1|1 么),我们有定理,拆点前最小路径点覆盖包含的路径条数等于 \(N\) 减去拆点后新图的最大匹配数

例题:捉迷藏

题意略。

分析:此题要求有向无环图的最小路径可重复覆盖,考虑在可重复的点两边,跨过这个点连边,也就是给所有可以间接到达的点之间连边,所以先跑一遍传递闭包再按照普通的最小路径覆盖求就好了。


二分图边染色问题

给定一张二分图,经过同一点的边不能染成相同的颜色,设此二分图所有点最大度数为 \(D(G)\),最少需要的颜色种类为 \(\Delta(G)\),有 \(D(G)=\Delta(G)\)


总结:
怎么什么都是最大匹配数最重要的是建模。

posted @ 2025-02-16 14:51  baiguifan  阅读(80)  评论(0)    收藏  举报