Skip to main content

图匹配

参考资料

二分图最大匹配

匈牙利算法依次为左部每个点寻找匹配。从一个点出发找 增广路——交替经过非匹配边与匹配边、两端均为非匹配点的路径,翻转其上的匹配状态即可让匹配数加一。match(u) 递归地为 uu 腾出一个可用的右部点。时间复杂度为 O(nm)O(nm)

147 Bcpp
bool match(int u)
{
for(auto v:G[u])
{
if(vis[v])continue;
vis[v]=1;
if(!a[v]||match(a[v]))
{
a[v]=u;
return 1;
}
}
return 0;
}

二分图最大权匹配

二分图最大权匹配KM 算法 求解。它给左右部每个点各一个 顶标 lx,lyl_x,l_y,只在满足 lx(u)+ly(v)=w(u,v)l_x(u)+l_y(v)=w(u,v)相等子图 上寻找完美匹配。

当相等子图上找不到增广路时,按当前交错树调整顶标,使更多边进入相等子图,直到匹配完美。朴素实现 O(n4)O(n^4),用 slack 数组优化后为 O(n3)O(n^3)

一般图最大匹配

一般图(不一定是二分图)的最大匹配用 带花树(Blossom)算法求解。它在 BFS 寻找增广路时,一旦遇到奇环(花)就把整朵花缩成一个点继续搜索,从而绕开奇环对增广的阻碍。复杂度 O(n3)O(n^3)

例题

给定一个二分图,其左部点的个数为 nn,右部点的个数为 mm,边数为 ee,求其最大匹配的边数。

左部点从 11nn 编号,右部点从 11mm 编号。

给定一个 NNMM 列的棋盘,已知某些格子禁止放置。

问棋盘上最多能放多少个不能相互攻击的車。

車放在格子里,攻击范围与中国象棋的「車」一致。

给定左、右各 nn 个点的二分图及若干带权边,求一个权值和最大的完美匹配,并输出该最大权值。

给定 nn 个点 mm 条边的无向图,求最大匹配的边数及任意一组方案。