HDU #2063 过山车 图的最大匹配 模板题 匈牙利算法

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

思路


这道题是图的最大匹配的模板题,利用匈牙利算法解决,其核心是可以通过不停地找增广路来增加匹配中的匹配边和匹配点。找不到增广路时,达到最大匹配(这是增广路定理)。
相关概念可参照我的另一篇博客:《二分图的最大匹配、完美匹配与匈牙利算法》。
也可以简单地理解为不断地转移而“腾出位子”,如果下一个女生匹配不上男生,则将查找前几位的女生是否可以通过”转移“而腾出一个男生使得该女生可以与他匹配。
AC代码如下,采用的是递归dfs隐式调用一个栈以实现匈牙利算法:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>

const int maxn = 510;
const int maxm = 510;
const int maxk = 1010;
int n, m, k; //二分图顶点数n 顶点数m 边数k
int line[maxm][maxn];
bool used[maxn];//used代表{n}中的某点有没有被匹配
int next[maxm];//next表示如果{n}中的某点被匹配到,那么是{m}中的哪一个点

//{m}中的x是否可以匹配{n}中的某点
bool find (int x) {
    for (int i = 1; i <= n; i++) {
        if (line[x][i] &&!used[i]) {
            used[i] = true;
            //如果{n}中的点没有匹配或其匹配的点可转移
            if (!next[i] || find(next[i])) {
                next[i] = x;
                return true;
            }
        }
    }
    return false;
}

int match() {
    int sum = 0;
    for (int i = 1; i <= m; i++) {
        memset(used, 0, sizeof(used));
        if (find(i)) sum++;
    }
    return sum;
}

int main(void) {
    int u, v;
    scanf("%d", &k);
    while(k && ~scanf("%d%d", &m, &n)) {
        memset(line, 0, sizeof(line));
        memset(next, 0, sizeof(next));
        while(k--) {
            scanf("%d%d", &u, &v);
            line[u][v] = 1;
        }
        printf("%d\n", match());
        scanf("%d", &k);
    }
    return 0;
}
hungarian.cpp
 
 
 

猜你喜欢

转载自www.cnblogs.com/Bw98blogs/p/8835776.html