1、网络流
给定一个二分图G = (X, E, Y)。构造与G对应的网络G‘, 构造方法如下:
(1)增加一个源点s, 一个汇点t 。
(2)从s向X的每个顶点引一条有向边,从Y的每个顶点向t引一条有向边。
(3)将原图G的每一条边改为从X指向Y的有向边。
(4)让所有的边容量为1 。
然后求最大流,就是二分图的最大匹配边数。
2、匈牙利算法
首先定义增广路:若P是图G种一条联通两个未匹配定点的路径,并且属于M的边和不属于M的边(已匹配的边和未匹配的边)在P上交替出现,则称P为相对于M的一条增广路。特别地,当一边(v, v')两端点均为非M-顶点,通路(v, v')亦称为增广路。
算法具体实现:
(1)首先用(*)标记X中所有的非M-顶点,然后交替进行步骤(2),(3)。
(2)选取一个刚标记(用(*)或在步骤(3)中用(yi)标记)过的X中顶点,例如顶点xi,然后用(xi)去标记Y中顶点y,如果xi与y为同一非匹配边的两端点,且在本步骤中y尚未被标记过。重复步骤(2),直至对刚标记过的X中顶点全部完成一遍上述过程。
(3)选取一个刚标记(在步骤(2)中用(xi)标记)过的Y中结点,例如yi,用(yi)去标记X中结点x,如果yi与x为同一匹配边的两端点,且在本步骤中x尚未被标记过。重复步骤(3),直至对刚标记过的Y中结点全部完成一遍上述过程。
(2),(3)交替执行,直到下述情况之一出现为止:
(Ⅰ)标记到一个Y中顶点y,它不是M-顶点。这时从y出发循标记回溯,直到(*)标记的X中顶点x,我们求得一条增广路。设其长度为2k+1,显然其中k条是匹配边,k+1条是非匹配边。
(Ⅱ)步骤(2)或(3)找不到可标记结点,而又不是情况(Ⅰ)。
(4) 当 (2),(3)步骤中断于情况(Ⅰ),则将增广路中非匹配边改为匹配边,原匹配边改为非匹配边(从而得到一个比原匹配多一条边的新匹配),回到步骤(1),同时消除一切现有标记。
(5)对一切可能,(2)和(3)步骤均中断于情况(Ⅱ),或步骤(1)无可标记结点,算法终止(算法找不到增广路)。
转自:http://hi.baidu.com/sysucs/blog/item/c1c58dee4c5247282df53484.html
2-21:
今天做一下补充,在Matrix67 大神的解释:
说穿了,就是你从二分图中找出一条路径来,让路径的起点和终点都是还没有匹配过的点,并且路径经过的连线是一条没被匹配、一条已经匹配过,再下一条又没匹配这样交替地出现。找到这样的路径后,显然路径里没被匹配的连线比已经匹配了的连线多一条,于是修改匹配图,把路径里所有匹配过的连线去掉匹配关系,把没有匹配的连线变成匹配的,这样匹配数就比原来多1个。不断执行上述操作,直到找不到这样的路径为止。
下面是匈牙利算法的实现:
1 bool dfs(int t) {
2 for(int i = 1; i <= stu; i++) {
3 if(!usd[i] && g[t][i]) {
4 usd[i] = true;
5 if(Link[i] == -1 || dfs(Link[i])) {
6 Link[i] = t;
7 return true;
8 }
9 }
10 }
11 return false;
12 }
13
14 for(i = 1; i <= cou; i++) {
15 memset(usd, 0, sizeof(usd));
16 if(dfs(i)) ans++;
17 }