二分图匹配的扩展问题

二分图匹配拓展问题
/**

    前面提到了匈牙利算法解决二分图匹配问题,但是基于二分图还有几个经常
    见的扩展问题如下:
        1、最大独立集点数
        2、最小顶点覆盖数
        3、最小路径覆盖数
    **********************************************************************
    最大独立集点数:

        有5个同学,小明,小强,小壮,小雨,小丽,现在要做游戏,可是小雨
    小丽都不喜欢小明,问最多能挑出多少学生使他们在一起玩???

    显然答案为4,直接把小明赶走即可,因为如果小明在,小雨和小丽两个女女
    就不干了。。

    *最大独立集点数 = N - 最大匹配数

    如下建图

       小雨 * * *小明
              *
       小丽 *    小强

                 小壮
    最大匹配为 1,有 5 个点,所以最大独立集点数为 5 - 1 = 4;
    **********************************************************************

    最小顶点覆盖数:
        即在二分图中用最少的点关联所有的边,如上图:最小顶点覆盖数为 1
    即小明一个人就关联了仅存的两条边。。

    最小顶点覆盖数 = 最大匹配数

    Konig定理:二分图的最小顶点覆盖数等于最大匹配数。
    网上有关于这个定理的证明。。。

    后面还会遇到树的最小支配集,即最少的点关联所有的点或边。。。
    树的最小支配集用贪心和树形DP 解决,后面会提到
    **********************************************************************

    最小路径覆盖
        路径覆盖就是在*无环有向图*中找一些路径,使之覆盖了图中所有顶点,且
    任何一个顶点有且只有一条路径与之关联。

    最小路径覆盖 = N - 最大匹配数

    **********************************************************************

        二分图匹配和网络流一样,都在于建图,应该说几乎所有的图论题都在于建图
    建图的技巧和难度,决定了这道题的质量和难度,所以会套模板是基础,建图才是
    王道……

    注意:上面3个只适用于有向无环图,当为无向图时可以通过拆点转换为无向图,但
    算出的最大匹配得除二。。 但不能有环

    拆点:N个点 则把 X 点拆成 2N+X 则 2N+X 完全等价X 去添边,即无向边ab,
    可拆成 a->2N+b b->2N+a。。用匈牙利算法算出最大匹配除二即为匹配

*/

收藏于 2011-11-23
来自于百度空间

### 匈牙利算法解决二分图匹配问题 #### 背景介绍 匈牙利算法是一种用于寻找二分图的最大匹配的有效方法。它基于增广路径的概念来逐步增加当前匹配的数量,直到无法再找到新的增广路径为止[^2]。 #### 增广路径定义 在一个二分图中,如果一条路径使得起点和终点都是未匹配的点,并且路径上的边交替处于已匹配状态和未匹配状态,则该路径称为增广路径。通过反转这条路径上所有边的状态(即将匹配变为未匹配,反之亦然),可以得到一个新的更大的匹配集[^3]。 #### Python代码实现详解 以下是利用Python实现匈牙利算法的一个具体例子: ```python def Matching(u, used, B, Graph): for i in range(1, len(Graph[u])): if Graph[u][i] == 1 and not used[i]: used[i] = True if B[i] == 0 or Matching(B[i], used, B, Graph): B[i] = u return True return False while True: try: k, n, m = map(int, input("请输入三个数以逗号隔开,分别代表边的个数、A集合元素个数、B集合元素个数:").split(",")) Graph = [[0 for _ in range(m + 1)] for __ in range(n + 1)] print("请输入k行,每行两个整数以逗号隔开,表示一条边") for _ in range(k): a, b = map(int, input().split(",")) Graph[a][b] = 1 B = [0] * (m + 1) ans = 0 for i in range(1, n + 1): used = [False] * (m + 1) if Matching(i, used, B, Graph): ans += 1 print(f"最大匹配是:{ans}") except Exception as e: break ``` 这段代码实现了基本的匈牙利算法逻辑,其中`Matching`函数负责查找是否存在增广路径并更新匹配关系;外部循环则遍历所有的可能起始节点尝试扩展匹配数量[^2]。 #### 步骤解析 - 初始化数据结构:创建邻接矩阵Graph以及记录右侧顶点匹配情况的一维数组B。 - 对于每一个左侧集合中的顶点执行DFS/BFS搜索操作试图发现新的可扩展示意子序列即所谓的“增广路”。 - 如果成功找到了这样的路径,则调整现有的配对方案使之容纳新加入的关系;否则继续处理下一个候选者直至全部考察完毕。 #### 示例应用 假设有如下输入: ``` 请输入三个数以逗号隔开,分别代表边的个数、A集合元素个数、B集合元素个数:4,3,3 请输入k行,每行两个整数以逗号隔开,表示一条边 1,1 1,2 2,2 3,3 ``` 程序会输出: ``` 最大匹配是:3 ``` 这表明在这个特定的例子中有三条独立边能够形成完美匹配[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值