二分图的最大匹配深搜算法

本文通过一个具体的游乐场组合问题实例,详细介绍了如何利用深度优先搜索(DFS)实现二分图的最大匹配算法。通过逐步解析算法流程,包括初始化、递归查找匹配以及更新匹配状态等步骤,帮助读者深入理解这一经典图论问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

Sample output

3


今天打算学习二分图匹配的一些知识,听队友说dfs的方法最容易理解效率也不错,早上看了一下确实如此。下面以此题为例讲解求解二分图最大匹配的算法。

以此题为例,第一个女生可以选择1,2,3,三个男生,第二个女生可以选择1,3两个男生,第3个女生可以选择第1个男生,使用贪心的思想,第一个女生先直接选择男生1,第二个女生再选择1,发现被选择了,这个时候有两种选择,第一不选择这个男生了,继续选择下一个男生,第二,让当前男生选择她,让之前的那个女生重新选择男生,这两者是有一个优先级的,如果直接不选择,可能这个女生接下来就没有能选择了,而前一个女生可能有多种选择,所以应该优先替换,如果替换失败,说明前一个女生也只有一个能选择,找不到新的男生了,这个时候当前女生就直接不选择了,因为反正只能选择一个,匹配数总是要少一个的。

分析之后,我们的算法就很显然了,依次处理女生,选择能选择的男生,如果该男生已经被选择过了,尝试替换,替换失败,没办法,考虑下一个男生。


#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int max_node = 200;
vector<int> G[max_node];
int node_num,edge_num;
int girl[max_node],boy[max_node]; //girl[i]=j表示标号为i的女孩和标号为j的女孩配对,boy[i]相反
bool vis[max_node]; //标记男生的选择情况

void init(){
    for(int i=0; i<max_node; i++){
        G[i].clear();
    }
}

int Find(int u){ //能否找到一个匹配
    for(int i=0; i < G[u].size(); i++){
        int x = G[u][i];
        if(vis[x]) continue;
        vis[x] = true;
        if( !boy[x] || Find(boy[x])){ // 对于当前x,如果x还没有选择则可以直接选择,如果强行选择x,则x原来匹配的女生需要替换
            girl[u] = x;
            boy[x] = u;
            return 1;
        }
    }
    return 0;
}

int max_match(){
    int ans = 0;
    memset(boy, 0, sizeof(boy));
    memset(girl, 0, sizeof(girl));
    for(int i=1; i<=node_num; i++){
        memset(vis, 0, sizeof(vis));
        ans += Find(i);
    }
}
int main(){
    freopen("input.txt", "r", stdin);
    while(scanf("%d%d" ,&node_num,&edge_num)!=EOF){
        init();
        int from, to;
        for(int i=1; i<=edge_num; i++){
            scanf("%d%d" ,&from, &to);
            G[from].push_back(to);
        }
        printf("%d\n" ,max_match());
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值