hdu2063匈牙利算法裸题
二分图就是一个无向图G=(V,E),如果顶点集V可分割为两个人互不相交的子集V1,V2,选择这样的子集中边数最大的子集称为图的最大匹配问题,匈牙利算法就是解决二部图匹配的最常见的算法。
其核心是寻找增广路径。
最关键的就是“腾”,递归过程实现,“有机会就上,没有机会创造机会也要上”。
hdu2063的代码
#include<iostream>
using namespace std;
#include<algorithm>
#include<string.h>
int m, n;//m个女生,n个男生
bool line[1005][1005];//存下可能有的关系
bool used[1005];//这个“男生”有没有被查询腾位置
int boy[1005];//女生跟哪个男生匹配
bool find(int x)
{
int i, j;
for (j = 1; j <= n; j++)
{
if (line[x][j] == true && used[j] == false)
//曾试图修改过这个j的匹配,但没有成功,所以就不要费功夫了。
{
used[j] = 1;
if (boy[j] == 0 || find(boy[j]))
{
boy[j] = x;
return true;
}
}
}
return false;
}
int main()
{
int k;
while (cin >> k >> m >> n)
{
if (k == 0)
break;
memset(line, 0, sizeof(line));
memset(girl, 0, sizeof(girl));
int i;
for (i = 0; i < k; i++)
{
int a, b;
cin >> a >> b;
line[a][b] = 1;
}
int sum = 0;
for (i = 1; i <= m; i++)//遍历每个女生
{
memset(used, 0, sizeof(used));//每个可能性都不能放过
if (find(i))
sum++;
}
cout << sum << endl;
}
return 0;
}
下面我们找一组数据跑一下试试
6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
从第一个女生开始,进入find(1),在find(1)中,遍历所有的男生,line(1,1)是可以的,然后boy[1],还没有匹配,所以boy【1】=1,return true;进入下一个女生find(2),line(2,1)=true,然后进入find(1),想要女生1给腾个地方,boy【2】=1,boy【1】=2;进入下一个find(3),在find(3)中,find(2),find(2)中,boy【3】=2,所以boy【1】=3,结束了。
再试一组吧。
7 4 4
1 1
1 2
2 2
2 3
3 1
3 2
4 3
开始扫第一个女生find(1),boy【1】=1,find(2),boy【2】=2,find(3),进入find(1),进入find(2),boy【3】=2,boy【2】=1,boy【1】=3,进入find(4),进入find(2),进入find(1),不可以return false。
还是没有特别懂算法的运行过程,就很气!