二分图 最小覆盖数 = 最大匹配数、最大独立集 = 总数-最小覆盖集 证明 hdu 1068

来源:互联网 发布:梦幻西游高级宝石算法 编辑:程序博客网 时间:2024/05/19 08:03


二分图有两个定理:最小覆盖数=最大匹配数、最大独立集=总数-最小覆盖集 。


几个基本定义

最小覆盖:即在所有顶点中选择最少的顶点来覆盖所有的边。

最大匹配:二分图左右两个点集中,选择有边相连的两个匹配成一对(每个点只能匹配一次),所能达到的最大匹配数。

最大独立集:集合中的任何两个点都不直接相连。

最小覆盖数=最大匹配数证明:

参考了别的博客,内容如下:

首先,我们要抓住二分图最大匹配后图的特点,此时,不存在增广路。如下图所示,该图为不完整的最大匹配后的二分图:

 

     红点为匹配点,蓝点为未匹配点。

     对于一个点而言,他所连接的点有这三种情况:

     1、只连接了红点;

     2、只连接了蓝点;

     3、连接了红点和蓝点。

     在上面的图中,x与y是所连接的边是匹配边。x连接了红点和蓝点,这个时候,y所连接的点一定没有蓝点,如果有,就是一条新的增广路,那么该图就不是最大匹配图了。

     另一点更明显,就是在最大匹配图中 不会出现一条边同时连接着两个蓝点。

     那么,对于一条边而言,只有两种情况:

     1、两端的点是红点;

     2、两端的点一点是红色,一点是蓝色。

     可知,一条边上,一定有红点,那么,我们就选择红点作为覆盖点。

     对于上面的匹配边xy,我们无论是选择x还是y都可以覆盖xy这条边,但是对于图中的蓝点而言,只能选择x作为覆盖点去覆盖那条边,这样,我们就选择x作为覆盖点,它所覆盖的边中,既包括了与他相连的那些蓝点的边,也包括了xy这条匹配边。因为y点没有蓝色连接点,所以,y不是必须选择的覆盖点,它与那些红点相连的边都可以选择那些红点来覆盖边。所以,对于一条匹配边而言,我们只需要选择其中一个点就可以覆盖完整个二分图里的边了。

    所以最小覆盖点数等于最大匹配。

最大独立集=总数-最小覆盖集证明:


上图,我们用两个红色的点覆盖了所有边。我们证明的前提条件是已经达到最小覆盖。

即条件1.已经覆盖所有边,条件2.所用的点数最小

首先我们来证明蓝色点组成的是一个独立集:如果有两个蓝色点间有边相连,那么这条边则没有被覆盖,则与条件1矛盾。因此是独立集。

再来证明这个独立集最大: 如果我们要再增加这个独立集中的点,则需要把某个红点变成蓝点。而由最小覆盖数=最大匹配数的证明我们知道,每一个红点是最大匹配中的一个匹配点,也就是说每个红点至少连接了一条边。因此当我们将某个红点变成蓝点时,我们需要牺牲的蓝点的个数是大于等于1的。也就是说,我们最多只能找到数量相等的其他独立集,而无法找到数量更大的。因此蓝色点集必定为最大独立集。 蓝色点数 = 总点数 - 红色点数,即最大独立集=总数-最小覆盖集

以hdu 1068为例:


实际上题目让我们求的就是最大独立集。我们将题中所有点写两遍,最后除2就是所求。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<math.h>using namespace std;vector<int>link[1005];bool vis[1005];int n,match[1005];bool find(int p){int i,j,len = link[p].size();for(i = 0; i < len; i++){if(!vis[link[p][i]]){vis[link[p][i]] = 1;if(match[link[p][i]] == -1 || find(match[link[p][i]])){match[link[p][i]] = p;return 1;}}}return 0;}int main(){//freopen("t.txt","r",stdin);int i,j,a,b,m,count;while(~scanf("%d",&n)){count = 0;for(i = 0; i < n; i++) match[i] = -1;  for(i = 0; i < n; i++){scanf("%d: (%d)",&a,&m);link[a].clear();for(j = 0; j < m; j++){scanf("%d",&b);link[a].push_back(b);}}for(i = 0; i < n; i++){memset(vis,0,sizeof(vis));if(find(i)) count++;}printf("%d\n",n-count/2);}}


2 0