二分图最大匹配-匈牙利算法

二分图最大匹配

设 G为二分图,若在 G 的子图 M中,任意两条边都没有公共节点,那么称M为二分图G的一组匹配。在二分图中,包含边数最多的一组匹配称为二分图的最大匹配。
在这里插入图片描述

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。

增广路:从一个未匹配点出发,走交替路,若能到达另一个未匹配点,则这条交替路称为增广路。
例如,3→5→1→4→2→7
如下图所示:
在这里插入图片描述

观察增广路,我们会发现:非匹配边比匹配边多一条。只要把增广路中的匹配边和非匹配边的身份交换(即倒过来走),交换后,图中的匹配边数目比原来多了1条。
如图所示:
在这里插入图片描述

这里的增广路就是指能增加匹配边的一条路。
匈牙利算法:通过不停地找增广路来增加匹配边。找不到增广路时,达到最大匹配。可以用DFS或BFS来实现。

匈牙利算法

男女相亲,男选女,可占可让,贪心配对

在这里插入图片描述
我们来看一道例题:
洛谷P3386

代码如下:

#include<iostream> // 引入输入输出库
using namespace std;

// 声明全局变量
int n, m, k, a, b, ans; // n: 左边节点数, m: 右边节点数, k: 边数, a, b: 边的两个端点, ans: 匹配的总数
const int M = 500005; // 定义最大边数
const int N = 500005; // 定义最大节点数
int h[N], idx; // h: 邻接表头, idx: 当前边的索引
int vis[N], match[N]; // vis: 访问标记数组, match: 匹配数组

// 边的结构体定义
struct edge {
    int v; // 边的终点
    int ne; // 下一个边的索引
} e[M]; // 声明边的数组

// 添加边到邻接表
void add(int a, int b) {
    e[++idx] = { b,h[a] }; // 将边(b, h[a])加入数组e,并更新邻接表
    h[a] = idx; // 更新节点a的邻接表头指向当前边
}

// 深度优先搜索尝试寻找增广路径
bool dis(int u) {
    // 遍历以u为起点的所有边
    for (int i = h[u]; i; i = e[i].ne) {
        int v = e[i].v; // 获取边的终点v
        if (vis[v]) { // 如果v已经被访问过
            continue; // 跳过
        }
        vis[v] = 1; // 标记v为已访问
        // 如果v没有匹配或者找到v的匹配节点的增广路径
        if (!match[v] || dis(match[v])) {
            match[v] = u; // 更新v的匹配为u
            return 1; // 找到一条增广路径
        }
    }
    return 0; // 未找到增广路径
}

int main() {
    cin >> n >> m >> k; // 输入左边节点数n、右边节点数m和边数k
    for (int i = 0; i < k; i++) { // 遍历每一条边
        cin >> a >> b; // 输入边的两个端点a和b
        add(a, b); // 添加边到邻接表
    }

    for (int i = 1; i <= n; i++) { // 对于每一个左边节点
        memset(vis, 0, sizeof(vis)); // 重置访问标记数组
        if (dis(i)) { // 尝试从节点i出发寻找增广路径
            ans++; // 如果找到增广路径,匹配数增加
        }
    }

    cout << ans << endl; // 输出最终的匹配数
    return 0; // 返回0,程序正常结束
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值