题目链接
https://www.luogu.com.cn/problem/P3386
题目大意
给定一个二分图,其左部点的个数为 \(n\),右部点的个数为 \(m\),边数为 \(e\),求其最大匹配的边数。
左部点从 \(1\) 至 \(n\) 编号,右部点从 \(1\) 至 \(m\) 编号。
题目解析
二分图最大匹配,一般用匈牙利算法完成。
匈牙利算法的本质,其实是不断尝试新匹配,修改旧匹配的 \(DFS\)。
点数为 \(n\),边数为 \(m\) 。
时间复杂度: \(O(nm)\)
题目中采用了数组邻接表的存图方法,\(v[x]\) 表示新一轮是否访问数组,设成 \(i\) ,可以免去每轮清空数组的 \(memset\)。
参考代码
#include <cstdio>
using namespace std;
int n, m, e, a, b, ans=0;
int h[1005], v[1005], p[1005];
struct AB{
int a, b, n;
} d[1000005];
int match(int a)
{
for (int j = h[a]; j ! =0; j = d[j].n)
{
int t = d[j].b;
if (v[t] != i)
{
v[t] = i;
if (!p[t] || match(p[t]))
{
p[t] = a;
return 1;
}
}
}
}
int main()
{
scanf("%d%d%d",&n, &m, &e);
for (int i = 1; i <= e; ++i)
{
scanf("%d%d",&a, &b);
if (b > m) continue;
d[i].a = a;
d[i].b = b;
d[i].n = h[a];
h[a] = i;
}
for (int i = 1; i <= n; ++i)
{
if (match(i)) ans++;
}
printf("%d\n",ans);
return 0;
}
感谢支持!