Issue:
Meaning:
- 可以理解为有
n
1
n_1
n1个男生和
n
2
n_2
n2个女生,然后有m对感情基础,然后要两两配对,求能配对成功的最大值;
Thinking:
- 构建
n
1
n_1
n1个链表,把男生作为表头,连接和他有感情基础的所有女生;
- 只要男生主动找女生就行,所有只需要add从男生到女生的有向图即可;
- 依次遍历
n
1
n_1
n1个男生,让他们依次找对象,如果能找到,就答案
res++
; - 每个男生依次遍历有感情基础的女生,用st[]数组来存是否追求过,追求过失败了就不能再追求;
- 用match[j]数组表示女生
j
j
j已经匹配的男生;
- 如果match[j] == 0, 表示目前的女生还没有被匹配,
x
∈
n
1
x \in n_1
x∈n1可以直接匹配;
- 如果match[j] != 0, 那么就看match[j]这个男生是否能换一个,如果能换,那也可以匹配;
- 找不到,就换链表里下一个女生;
- 每个女生都不能和x匹配成功,那么x就不能为答案做出贡献;
- 时间复杂度
O
(
n
m
)
O(nm)
O(nm),实际远小于
O
(
n
m
)
O(nm)
O(nm);
Code:
#include <cstring>
#include <iostream>
using namespace std;
const int N = 510, M = 100010;
int n1, n2, m;
int h[N], e[M], ne[M], idx;
int match[N];
bool st[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool find(int x)
{
for (int i = h[x]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j])
{
st[j] = true;
if (match[j] == 0 || find(match[j]))
{
match[j] = x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d%d%d", &n1, &n2, &m);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
}
int res = 0;
for (int i = 1; i <= n1; i ++ )
{
memset(st, false, sizeof st);
if (find(i)) res ++ ;
}
printf("%d\n", res);
return 0;
}
Tips:
- 匈牙利算法模板题。