【图论】二分图多重匹配 の探讨

本文探讨了二分图多重匹配的概念,其中每个左侧点都有一个唯一输出,而右侧点可以有多个输入。介绍了如何在约束条件下寻找最大匹配,通过二分枚举结合匈牙利算法进行求解。举例分析了POJ2289、POJ2112和POJ3189等题目,展示了如何应用这些方法解决实际问题。
摘要由CSDN通过智能技术生成

在这里插入图片描述这几个题是我觉得比较好的入门二分多重匹配的题。


什么是二分多重匹配?
简单的来说,就是一个对于左边(或者右边)的点集,每个点都要有单独输出的完备匹配,但是其对应的另一侧点集,每个点可以有多个输入(有些点甚至可能没有输入也有可能),简单的来说就是:目标方可以有多个输入吧,输出方每个只能单个输出,保障每个输出方点均有输出。

既然是要多重,那么我们就会有一定的约束条件。比如POJ2289:意思就是每个人都要有对应的点,你要保证最大点的集合中包含人的数量最少。这就是一种限制性条件。那么怎么去解决这个问题呢?这时候就需要运用二分枚举了,我们可以通过二分最大点包含人的数量的个数来进行收缩,最后当l==r时,这个r就是我们索要求的结果了。二分方法比较好理解。
在这里插入图片描述
那么我们该怎么去找想要的多重匹配呢?这其实是匈牙利算法的一种优化。我们给出当前限制条件 d(也就是二分的mid),通过记录目标点v接受次数及其对应所接受的u来进行匈牙利算法,如果v的次数len[v] < d,那么我们还可以通过添加增广路使len[v]++,如果len[v]==d了,那么我们可以利用匈牙利算法的思维,去遍历0~len[v]-1,这里面的u,通过改变u的交替路径来使当前增广路成立,如果无论怎么改都不成立,那么就结束了。此时即是最大情况了。

对于例题POJ2112来说,这也是一个很经典的多重匹配问题。他把牛的集合当做发送集合,棚的集合当做接受集合,二分的对象是路径(怎么求最小路径?用Floyd算法求多源最短路即可),每个棚最多塞k个(多重匹配的约束条件是k),然后当你求MatchMax的时候,记住当前投入的都是可以到达的路径(反正求得的最短路径>二分约束条件d的我都当做不可到达),并添加至mp[u][v]数组之中。这样问题就简化成和POJ2289一样的很裸的板子问题了。

对于例题POJ3189来说,同样很经典,二分的是距离len(1-B中),与以上两题不同的是每一个点都有其专属的约束条件limit[i]。我们期望二分的mid(len)尽可能的小,所以需要另外的一种for遍历,遍历[i,i+len-1],去抠范围,而此时上面的L=i,R=i+len-1所对应的就是1-B中的范围。这题匈牙利算法运用范围是L-R,和上面2题1-N又有点不一样,这个L,R怎么来的我刚才已经说了。所以这题还是很经典的吧。

然后我展示一下POJ2112的AC代码吧(用作板子了)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define mem(a) memset(a,0,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=1e9+
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值