分析&题解:
这是道非常裸的二分图匹配,建好图后,直接用匈牙利DFS搜索即可。(这里采用遍历女生节点,找男生匹配,因为二分图以及给好了,并且确定左边是女生节点,右边是男生节点,所以可以这样做,如果混合给参考二分图匹配/判断中的匈牙利算法写法)关键步骤解释:
1.DFS代码:
bool DFS(int x)//搜索女生节点x
{
for(int i=1;i<=m;i++)//找男生匹配
{
if(!Edges[x][i]||flag[i])//i不在x出发的交替路里或者只是交替路不是增广路。
continue;
flag[i] = 1;//生成交替路;
if(!mark[i]||DFS(mark[i])) //i点未被匹配,或者i已经被匹配时寻找男生i所对应的女生的增广路,如果那个女生能找到另一条增广路径,即有另外的男生可以匹配那就更换
{
mark[i] = x;
return 1;
}
}
return 0;
}
2.Hungarian算法:
void Hungarian()
{
int ans = 0;
memset(mark, 0, sizeof(mark));//先初始化匹配数组为0
for(int i=1;i<=g;i++)
{
memset(flag, 0, sizeof(flag));//每次初始化交替路数组为0
if(DFS(i))
{
ans++;//匹配成功就++;
}
}
cout << ans << endl;
}
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
bool Edges[666][666];
int mark[666];
bool flag[666];
int k,g,m;
void input()
{
for(int i=0;i<k;i++)
{
int x,y;
cin >> x >> y;
Edges[x][y] = 1;
}
}
bool DFS(int x)
{
for(int i=1;i<=m;i++)
{
if(!Edges[x][i]||flag[i])
continue;
flag[i] = 1;
if(!mark[i]||DFS(mark[i]))
{
mark[i] = x;
return 1;
}
}
return 0;
}
void Hungarian()
{
int ans = 0;
memset(mark, 0, sizeof(mark));
for(int i=1;i<=g;i++)
{
memset(flag, 0, sizeof(flag));
if(DFS(i))
{
ans++;
}
}
cout << ans << endl;
}
int main()
{
while(cin >> k && k)
{
cin >> g >> m ;
memset(Edges, 0, sizeof(Edges));
input();
Hungarian();
}
return 0;
}