匹配问题学习小结(POJ)

转自:http://www.cppblog.com/abilitytao/archive/2009/10/21/99124.aspx

临行上海,决定把最近研究过的各种匹配题做个汇总,原因是这样既可以巩固自己对匹配问题的掌握,又可以借此复习一下匹配问题的各种外在表现形式。我认为,如果比赛中出到匹配,出题者在问题的算法上大做文章的可能性不大,大多数出题者一定会挖空心思来设计一个让你眼花缭乱的背景,借此来隐藏匹配问题的实质!



二分图最小覆盖的Konig定理及其证明

二分图:

顶点可以分类两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y。

最小覆盖:

最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数

Konig定理:

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

证明:

为主便叙述,假设G分为左边X和右边Y两个互不相交的点集。。。。。。

假设G经过匈牙利算法后找到一个最大匹配M,则可知G中再也找不到一条增广路径。

标记右边未匹配边的顶点,并从右边未匹配边的顶点出发,按照边:未匹配->匹配->未匹配...,的原则标记途中经过的顶点,则最后一条经过的边必定为匹配边。重复上述过程,直到右边不再含有未匹配边的点。

记得到的左边已标记的点和右边未标记的点为S, 以下证明S即为所求的最小顶点集。

1。| S | == M
显然,左边标记的点全都为匹配边的顶点,右边未标记的点也为匹配边的顶点。因此,我们得到的点与匹配边一一对应。

2。S能覆盖G中所有的边。

上途S中点所得到的边有以下几种情况:

(1)左右均标记;

(2)左右均无标记;

(3)左边标记,右边未标记;

若存在一条边e不属于S所覆盖的边集,则e 左边未标记右边标记。

如果e不属于匹配边,那么左端点就可以通过这条边到达(从而得到标记);如果e属于匹配边,那么右端点不可能是一条路径的起点,于是它的标记只能是从这条边的左端点过来的左端点就应该有标记。



3。S是最小的覆盖。

因为要覆盖这M条匹配边至少就需要M个点。

转自:http://yejingx.ycool.com/post.2801156.html#



在一个PXP的有向图中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每每条路径就是一个弱连通子集.

由上面可以得出:

1.一个单独的顶点是一条路径;

2.如果存在一路径p1,p2,......pk,其中p1 为起点,pk为终点,那么在覆盖图中,顶点p1,p2,......pk不再与其它的顶点之间存在有向边.

最小路径覆盖就是找出最小的路径条数,使之成为P的一个路径覆盖.

路径覆盖与二分图匹配的关系:

最小路径覆盖=|P|-最大匹配数;

其中最大匹配数的求法是把P中的每个顶点pi分成两个顶点pi'与pi'',如果在p中存在一条pi到pj的边,那么在二分图P'中就有一条连接pi'与pj''的无向边;这里pi' 就是p中pi的出边,pj''就是p中pj 的一条入边;

对于公式:最小路径覆盖=|P|-最大匹配数;可以这么来理解;

如果匹配数为零,那么P中不存在有向边,于是显然有:

最小路径覆盖=|P|-最大匹配数=|P|-0=|P|;即P的最小路径覆盖数为|P|;

P'中不在于匹配边时,路径覆盖数为|P|;

如果在P'中增加一条匹配边pi'-->pj'',那么在图P的路径覆盖中就存在一条由pi连接pj的边,也就是说pi与pj 在一条路径上,于是路径覆盖数就可以减少一个;

如此继续增加匹配边,每增加一条,路径覆盖数就减少一条;直到匹配边不能继续增加时,路径覆盖数也不能再减少了,此时就有了前面的公式;但是这里只 是说话了每条匹配边对应于路径覆盖中的一条路径上的一条连接两个点之间的有向边;下面来说明一个路径覆盖中的每条连接两个顶点之间的有向边对应于一条匹配 边;

与前面类似,对于路径覆盖中的每条连接两个顶点之间的每条有向边pi--->pj,我们可以在匹配图中对应做一条连接pi'与pj''的边, 显然这样做出来图的是一个匹配图(这一点用反证法很容易证明,如果得到的图不是一个匹配图,那么这个图中必定存在这样两条边 pi'---pj'' 及 pi' ----pk'',(j!=k),那么在路径覆盖图中就存在了两条边pi-->pj, pi--->pk ,那边从pi出发的路径就不止一条了,这与路径覆盖图是矛盾的;还有另外一种情况就是存在pi'---pj'',pk'---pj'',这种情况也类似可证);

至此,就说明了匹配边与路径覆盖图中连接两顶点之间边的一一对应关系,那么也就说明了前面的公式成立!

转自:http://hi.baidu.com/cjhh314/blog/item/ded8d31f15d7510c304e1591.html





POJ 1469 COURSES
学生选课问题,基础匹配问题。
有p节课,n个学生,每节课可以由指定的几个学生参加,但是每个学生只能参加一节课。现在问能不能找到一些学生使得他们:
1.每个学生匹配不同的一节课
2.每节课匹配一个学生。
就是求个最大匹配,看看匹配数是不是等于课程数。如果相等不就满足要求了么.


POJ 3041 Asteroids
在N*N的平面上有K颗小行星,现在你要摧毁他们,你的每一发子弹可以摧毁同一行,或者是同一列上的小行星,现在问你最少要多少子弹才能摧毁所有的小行星?
构图:如果在i行j列上有一颗小行星 则graph[i][j]=1,再求最大匹配即可。
这一题用到的结论是 :最小顶点覆盖 = 最大匹配(最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联)


POJ 2771 Guardian of Decency
老师带学生出去旅游,但是担心学生会发生恋爱关系,所以带出去的学生至少要满足以下要求之中的一个:
1.身高相差40cm以上
2.同性
3.喜欢的音乐风格不同
4.喜欢的运动相同
问最多可以带出去多少学生?

个人感觉如果有男有女,就很有可能是二分匹配了。
这道题我们反过来想,如果将所有可能发生恋爱关系的男女配对,那么可以带出去的人数应该等于这个二分图的最大独立集。
根据公式: 最大独立集=顶点数(包括X和Y)-最大匹配
求一次匹配即可。

POJ 3020 Antenna Placement
题目的意思大致就是,一个矩形中,有N个城市,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市。
问至少放置多少个基站才能使得所有的城市都覆盖无线?
构图:行扫描所有城市,编号,如果有城市相邻就连一条边,当然如果3和4相邻,首先graph[3][4]=1,当扫描到4时graph[4][3]也连一条边,最后只需要取一半即可.求最大匹配的一半,这样可以得到所有2个相邻城市被一个基站覆盖所需要的基站数。然后再加上独立的那些基站即可。
公式是:N-最大匹配(代表所有可以和相邻城市配对的城市数)+最大匹配/2=N-最大匹配/2;

POJ 1325 Machine Schedule
两台机器A,B,A有n个模式,B有m个模式,现在有k个工作,其中每一个工作可以由A或B中的一个特定模式来完成,但是切换机器的模式要重新启动一次,问最少要重启多少次机器才能完成所有工作?
A,B两台机器构成一个二分图,在之间按照给出的条件连边。这样想,每一个工作其实是由一条边来代表的,那么我们只要用最少的顶点来覆盖所有的边即可。这就是最小覆盖。
根据公式:最小覆盖=最大匹配;
对原二分图做一次最大匹配即可。
对了,针对这个题还有一个问题,就是起始状态下是在mode 0的,如果在这个模式下工作,是不需要切换mode的,所以只要有工作是在mode 0下(不管是在A还是在B),对这个工作就不连边,默认它不占匹配数!记得当时就是错在这里,转化很重要啊!

POJ 2226 Muddy Fields(*)
这个题的原型应该是Asteroids的变种,刚看了这道题,一眼就看出了是最小覆盖,看来我理解了最小覆盖的内在含义了。
农夫John的养牛场,是一个R 行C 列的矩形,一场大雨后,养牛场低洼的地方都有了积水。John 的牛都很娇贵的,他们吃草的时候,不想把他们的蹄子给弄脏了。为了不让牛儿们把它们的蹄子弄脏,John 决定把有水的地方铺上木板。他的木板是宽度为1,长度没有限制的。
他想用最少数目的木板把所有有水的低洼处给覆盖上,前提是木板不能覆盖草地,但是可以重叠。
Sample:
4 4
*.*.
.***
***.
..*.


把行里面连在一起的坑连起来视为一个点,即一块横木板,编上序号,Sample则转化为:

1 0 2 0
0 3 3 3
4 4 4 0
0 0 5 0

把这些序号加入X集合,再按列做一次则为:

1 0 4 0
0 3 4 5
2 3 4 0
0 0 4 0

同样加入Y集合,一个坑只能被横着的或者被竖着的木板盖住,将原图的坑的也标上不同的序号,一共九个坑

1 . 2 .
. 3 4 5
67 8 .
. . 9 .

比如7号坑可以被横着的4号木板和竖着的3号木板盖住,把每个点的对应的横木板(4)和竖木板(3)中间连一条边的话,则问题转化为 找尽量少的边把这些点都盖住,根据定理便是求最大匹配数.

POJ 1422 Air Raid 空袭!
典型的最小路径覆盖题,城市之间单向相连,无环!问最少用多少个伞兵能遍历这张图。
根据定理:最小路径覆盖=顶点数-最大匹配数


POJ 3216 Repairing Company(*)
题目说的是一个城市里面有Q个点,有M项工作,每个工作有个工作地点pi,最晚开始时间ti,和工作需要的时间di.
从城市中的任意一个点到另一个点的直接时间又一个矩阵给出。不连通为-1.注意间接联通是被允许的。
我再这个题上哉了2次,汗啊。我总是以为二分图的顶点时基于城市中的点的,但实际上时基于工作。

这一题首先对给定的图做一次floyd,这样就能求出两个点之间最少需要走的时间。
然后判断两个工作之间是否存在先后关系

for(i=1;i<=m;i++)
{

scanf("%d%d%d",&work[i].p,&work[i].t,&work[i].d);
}
for(i=1;i<=m;i++)
for(j=1;j<=m;j++)
{

if(work[i].t+work[i].d+g[work[i].p][work[j].p]<=work[j].t)
graph[i][j]=1;
}


最后做最小路径覆盖即可。注意这里的顶点数应该是工作数!这一题值得重点注意!!!
printf("%d\n",m-Hungary(m,graph));

POJ 2594 Treasure Exploration(*)
太经典了,最小路径覆盖之变形!如果题目中有暗示此图无环且路径是单向的话,必然是最小路径覆盖无疑!
这个题的题目意思和那个伞兵题差不多,但是伞兵走过的路径是可以交叉的,这样我们先做一个传递闭包,然后再连边做最小路径覆盖即可。

POJ 1034 The dog task
一个很明显的二分匹配,不过和计算几何联系起来了。这道题目建图很巧妙.以BOB行走的n-1条有向线段为X,m个景点为Y,二分匹配。


暂时总结到这,对于匹配问题,我只想说,匹配问题,你真的很"2"!

你可能感兴趣的:(数据结构与算法)