Problem Description
RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?
Input
输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。0<K<=1000
1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。
Output
对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。
Sample Input
6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0
Sample Output
3
匈牙利算法:
以样例为例:
#include<bits/stdc++.h>9
using namespace std;
int k, m, n, ans;
int g[505][505]; // 邻接矩阵
int vis[505]; // 右点是每次为一个点配对时,标记配对点是否访问 (会更改其他的配对情况)
int linker[505]; // 存右点的对象即,下标是左点,存的内容是他的对象
bool dfs(int u) {
for(int i = 1; i <= n; i++) {
// 如果能够匹配,并且右边的节点没有被匹配
if(g[u][i] && !vis[i]) {
vis[i] = 1; // 标记右边的节点
// 如果右边节点没有匹配 或者
//右边节点的匹配对象,可以重新和其他右边节点匹配(注意这时候,vis标记的就起作用了。
//因为当前节点已经匹配了目前的i,而目前的i和之前上一个左边的节点匹配了,
//所以在搜索上一个左边节点的匹配对象时,是不能和当前右边节点i进行匹配。
if(!linker[i] || dfs(linker[i])) {
linker[i] = u; // 匹配成功,存下右边节点的左边匹配对象
return true; // 返回true;
}
}
}
return false; // 当遍历所有的结果都找到时,说明当前左边节点无法和右边节点匹配,返回false
}
// 匈牙利算法
int hungary() {
ans = 0;
memset(linker, 0, sizeof(linker)); // 将男女所有联系清空
for(int i = 1; i <= m; i++) {
// 对左边每一个节点匹配时,清空"右边已匹配的数组"vis数组
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++; // 搜索寻找可以匹配的对象
}
return ans;
}
int main() {
while(scanf("%d", &k), k) {
int a, b;
// 注意这里需要对g数组初始化, 因为对g数组的输入不是每个g[i][j]都输入
memset(g, 0, sizeof(g));
scanf("%d %d", &m, &n);
for(int i = 0; i < k; i++) {
scanf("%d %d", &a, &b);
g[a][b] = 1; // 将可能的配对赋值为1
}
printf("%d\n", hungary());
}
return 0;
}