匈牙利算法是要在给出一个匹配的基础上对每个非饱和点进行判断,看能否找到增广路,这边以空集为最初的集合,对每个点进行访问,寻找增广路,然后因为增广路的定义可以知道,只要找到一条增广路,肯定可以增加一条匹配边。
(增广路定义:一般是从非饱和点开始走非匹配边再匹配边,直到找到另一个非饱和点为止,(如果找不到匹配边,找一条非匹配边以非饱和点结尾的也行))
找到一条增广路,就把这个增广路的边集和原来的匹配集做异或操作(原来相同的边去掉,不同的边加入到集合中)
可以写一个find函数看能不能找到增广路,st数组是为了防止搜到同一个点出现死循环
function<bool(int)> find = [&](int u)
{
for (const auto &i : g[u])
{
if (!st[i]) // 如果没走过
{
st[i] = 1;
if (!match[i] || find(match[i]))
{
// 如果这个点没匹配或者可以找到一条增广路
match[i] = u;
return true;
}
}
}
return false;
};
match[i]表示第二个集合中的点i匹配的点是match[i]这个点
容易发现一个特点,只需要存一个方向的边就行了,所以从第一个点开始每个点都是非饱和点,就可以开始找增广路。
模板题:【模板】二分图最大匹配 - 洛谷
补充个结论:最大匹配数=最小点覆盖数