匈牙利算法(二分图匹配)

来源:互联网 发布:java随机读取数组的值 编辑:程序博客网 时间:2024/05/29 09:03

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。

还是没有特别懂算法的运行过程,就很气!