二分图

一.概念

(1)二分图:
是图论中的一种特殊模型。若能将无向图G=(V,E)的顶点V划分为两个交集为空的顶点集,并且任意边的两个端点都分属于两个集合,则称图G为一个为二分图。

(2)匹配:
一个匹配即一个包含若干条边的集合,且其中任意两条边没有公共端点

(3)最大匹配:
在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配。选择这样的边数最大的子集称为图的最大匹配问题,最大匹配的边数称为最大匹配数.

(4)完全匹配:
如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。

(5)最优匹配:
最优匹配又称为带权最大匹配,是指在带有权值边的二分图中,求一个匹配使得匹配边上的权值和最大。一般X和Y集合顶点个数相同,最优匹配也是一个完备匹配,即每个顶点都被匹配。如果个数不相等,可以通过补点加0边实现转化。一般使用KM算法解决该问题。

(6)最小顶点覆盖:(最少的点覆盖所有的边)
用最少的顶点数使得二分图G中的每条边都至少与其中一个点相关联,二分图的最小顶点覆盖数=二分图的最大匹配数;

(7)最小边覆盖(最小路径覆盖):(最少的边覆盖所有的点)
是指用尽量少的不相交简单路径覆盖二分图中的所有顶点。二分图的最小路径覆盖数=总点数-二分图的最大匹配数;

(8)最大独立集:
最大独立集是指寻找一个点集,使得其中任意两点在图中无对应边。对于一般图来说,最大独立集是一个NP完全问题,对于二分图来说最大独立集=总点数-二分图的最大匹配数。
二分图的最大独立集等于其补图的最大团(一个点集,满足点两两之间都有边相连)

二.匈牙利算法

匈牙利算法的基本步骤是:

int DFS(int x)
{
    for (int i=1;i<=m;i++)
        if (a[x][i] && !vis[i]) //与x相邻并且没有被遍历
        {
            vis[i]=1; 
            if (!d[i] || DFS(d[i]))
            //如果是未匹配点,则说明交替路为增广路,那么就交换路径(初始是未匹配边,最后也是,所以比匹配边数量大1)
            {
                d[i]=x;
                return 1;//找到了增广路 
            }
        }
    return 0;//没找到增广路 
}

主函数大体如下:

for (int i=1;i<=n;i++) //每次以其中一边的点为标准去遍历
{
    for (int j=1;j<=m;j++) vis[j]=0; //将另一边的点是否已经遍历的状态清空
    if (DFS(i)) ans++; //就算以后被修改了,但是总数还是不会改变的
}

三.Hall定理

(1)内容:
对于二分图 \(G=\{S \cup T,E\}\),设\(S' \subseteq S\),且在 \(T\) 中与 \(S'\) 相连的集合为 \(T'\),存在完美匹配当且仅当 \(|S'|<=|T'|\)
(2)必要性证明:
对于某 \(k\) 个点,如果与它们相连的点都不足 \(k\) 个那显然不可能存在完美匹配。
(3)充分性证明:
如果一个二分图满足Hall定理,但是不存在完美匹配,那么一定可以找到一个未匹配的点 \(A\) ,并且它一定连出了至少一个点 \(B\) ,如果 \(B\) 不在最大匹配中,那么它们就匹配了,显然矛盾。如果在最大匹配中,那么设与 \(B\) 点匹配的点为 \(C\) 。根据Hall定理,\(C\) 点一定还连有其它的点,如果连的是未匹配点,那么就是一条增广路,与最大匹配不符。那么只能是匹配点......如此循环下去,\(A\) 点所在的一边一定会比另一边点数多1,与Hall定理不符。
所以,得证。

四.例题

1.bzoj3175 [TJOI2013]攻击装置

Description

给定一个01矩阵,可以在0的位置放置攻击装置。每一个攻击装置 \((x,y)\) 都可以按照“日”字攻击其周围的8个位置,求在装置互不攻击的情况下,最多可以放置多少个装置。
\(N \leq 200\)

Solution

对图进行黑白染色,从而将图分成两个集合,可以互相攻击到的点连边,求最大独立集即可。
但是在黑白染色的时候一定要注意,不能只从 \((i-1)*n+j\) 的奇偶性来染色!!!这里我调了好久......
当然,不染色也是可以的。
code

2.bzoj3546 [ONTAK2010]Life of the Party

Description

给定一个二分图最大匹配,求出所有关键点(一定在最大匹配中的点)。
\(n,m \leq 10^4\)

Solution

做法不难想到,两边分别先求出一个最大匹配,此时关键点一定在匹配点中,对于所有的非匹配点,按照非匹配边,匹配边,非匹配边,匹配边......的顺序走下去,因为为偶交替路,所以所有的边均可交换,那么经过的所有同侧的点,显然都不是关键点。

code

3.bzoj4554 [HEOI2016/TJOI2016]游戏

Description

给定一张 \(n*m\) 的地图,在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。

\(n,m \leq 50\)

Solution

这道题目,我开始的想法是:对于所有空格,向所有可以威胁到的空格连边,最后求最大独立集,但是答案有问题。为什么呢?因为这个不一定满足二分图的最基本的性质:将图中的点分为两部分,同侧的点没有边相连。

所以对于每一行、每一列以硬石头为界分为很多个块。那么对于每一个块都最多只能放一个炸弹。所以就可以对于每一个空地,将其所在横向块、纵向块连边,跑匈牙利就行了。

code

4.P2764 最小路径覆盖问题

Description

给定有向图G=(V,E)。设P 是G 的一个简单路(顶点不相交)的集合。如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖。P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖。

对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
\(n \leq 100,m \leq 6000\)

Solution

一开始,我还想用拓扑的方法去做,但是有问题?

并不知道该怎么转为二分图,看了网上的题解之后......拆点。
每在二分图上连一条边,就相当于将两条路径连成一条,那么最小路径覆盖数就减少了1
然后,就没什么好说的了。

code

5.bzoj1143 [CTSC2008]祭祀

Discription

给出一个 \(n\) 个点 \(m\) 条边的有向无环图,要求选出一些点,满足任意两点均不可达,求最大点数。
\(n \leq 100,m \leq 1000\)

Solution

与上题类似,但是需要先 \(Floyd\) 传递闭包。
为什么这题需要先传递闭包呢?

这里要区分两个概念:

最小不相交路径覆盖:可以用上题的方法求出。
最小相交路径覆盖:需要先传递闭包,再进行匹配!!

例如这组数据,\(n=5,m=4\),有向边

1 3
2 3
3 4
3 5

答案分别为 3 和 2。

code

6.bzoj3140 [HNOI2013]消毒

Description

一个长方体,其尺寸为 \(a*b*c\)\(a、b、c\) 均为正整数。它被划分为\(a*b*c\)个单位立方体区域,每个单位立方体尺寸为111。用(i,j,k)标识一个单位立方体,1<=i<=a,1<=j<=b,1<=k<=c。现在要求将其中一些单位立方体区域进行消毒操作(每个区域可以被重复消毒)。每次对尺寸为xyz的长方体区域(它由xyz个单位立方体组 成)进行消毒时,需要min{x,y,z}的代价。求最小代价。

\(a*b*c \leq 5000\)

Solution

先考虑二维的情况,因为是取min,所以二维就只选择 \(1*n\) 的长方形,这样显然是最优的。那么就是每次可以消一行或一列,要求用最小的次数将所有1消去,这个用匈牙利算法可以很快解决,方法是套路的。

对于三维的情况,因为\(a*b*c \leq 5000\),所以最小的最大为17,所以就可以状压,枚举哪些层是整层消去,剩下的合并一下状态即可。

这道题思路清晰,但是打起来很麻烦,光是将a,b,c中最小的选出来处理就够我受的了......我还是看了网上的题解才知道有这种方法的,一开始我还在用vector......

这道题目还需要有很多的优化,不然过不了。

code

7.bzoj2744 [HEOI2012]朋友圈

Description

在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着。
一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目。两个国家看成是AB两国,现在是两个国家的描述:
A国:每个人都有一个友善值,当两个A国人的友善值a、b,如果a xor b mod 2=1,那么这两个人都是朋友,否则不是;
B国:每个人都有一个友善值,当两个B国人的友善值a、b,如果a xor b mod 2=0 或者 (a or b)化成二进制有奇数个1,那么两个人是朋友,否则不是朋友;
A、B两国之间的人也有可能是朋友,数据中将会给出A、B之间“朋友”的情况。
对于朋友的定义,关系是是双向的。
在AB两国,朋友圈的定义:一个朋友圈集合S,满足
\(S \subset A \cup B\) 对于所有的 \(i,j \in S\) ,i 和 j 是朋友
由于落后的古代,没有电脑这个也就成了每年最大的难题,而你能帮他们求出最大朋友圈的人数吗?
\(|A| \leq 200,|B| \leq 3000\)

Solution

先只看A国人:只有两个数一奇一偶时才能成为朋友,那么它们的关系构成了一个二分图,二分图的最大团为2。
再看B国人:奇数和奇数、偶数和偶数是两两相连的,一些奇数和一些偶数有边相连,发现它们关系的补图构成了一个二分图!而二分图的最大独立集等于其补图的最大团!!
所以我们先枚举在A国人中不选,选一个人,选两个人,然后拿出与选出的人相连的B国人,并建出补图,求出最大独立集即可。

还是卡时间,先把图建出来,然后再在图上选择一些点跑匈牙利。
还有,要用领接表存图!!!

code

8.bzoj4950 [Wf2017]Mission Improbable

Description

给一些单位立方体堆在 \(n*m\) 的方格中,每个方格中会堆若干个点,要求从其中移除尽量多的立方体使得原来的三视图不变。
\(n \leq 100,m \leq 100\)

Solution

每一行每一列的最高的肯定不能动。为了保证俯视图不变,首先先将所有的高度变为1,然后再将每一行每一列的最高的加上,但是会有一些满足既是每一行的最高的也是每一列最高的,求最大匹配即可:对于方格中的每一个点,如果所在的一行一列的最高的高度相同,则连边。

code

猜你喜欢

转载自www.cnblogs.com/Wuweizheng/p/9096833.html