二分图最大匹配(匈牙利算法,Dinic网络流算法)

article/2025/9/17 9:29:42

二分图最大匹配

二分图最大匹配问题: 有两个集合A,B,两个集合间有多条边连接集合中的点,且单个集合中的点各不相连,求两集合的点能两两配对的最大匹配数.

(参考:)二分图最大匹配——匈牙利算法
匈牙利算法: A集合记录各点与B集合相连的点,B集合记录某点与A集合中匹配的点.遍历A集合中的每一点,寻找最大匹配.

每一点顺序选取B集合中没被匹配过的点,若有,则将B集合中的点与该点匹配,跳转至下一个点.
若没有未匹配的点,顺序遍历所有有连接的点,看该点已匹配的点能否选择其他点去匹配,这是一个递归过程.

如:A1与B1,B2连;A2与B1,B2,B3连;A3与B1,B2连.在处理A3前,A1-B1,A2-B2相匹配,处理A3时,发现所有与A3相连的点都有匹配对象了.这时递归到B1匹配点A1,发现A1其他的点也均被匹配;再递归除B1外的第一个B2,发现B2的匹配点A2可以匹配B3,所以可以增加最大匹配数.
此时,令A2-B3,递归返回,A1-B2,递归返回,A3-B1.

时间复杂度:O(nm)(也称O(VE))

例题:P3386 【模板】二分图最大匹配

#include<bits/stdc++.h>
#define MAXN 505
using namespace std;struct Hungary
{struct NODE{int f,vis;set<int>to;};NODE node[MAXN];void add(int u,int v){node[u].to.insert(v);}int dfs(int x){if(node[x].vis)return 0;node[x].vis=1;for(auto& j:node[x].to){if(!node[j].f||dfs(node[j].f)){node[j].f=x;return 1;}}return 0;}int hungary(int n){int tot=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){node[j].vis=0;}tot+=dfs(i);}return tot;}
};int n,m,e,u,v;
Hungary a;
int main()
{cin>>n>>m>>e;for(int i=1;i<=e;i++){cin>>u>>v;a.add(u,v);}int tot=a.hungary(n);cout<<tot;return 0;
}

Dinic网络流算法:
需要了解网络流

设立超级源点s和超级汇点t,作s到A集合所有点的有向边,B集合所有点到t的有向边,A,B集合的边按题目连接,所有边的最大容量设置为1。最终流向t的最大流即为二分图最大匹配。

这个算法比匈牙利稍快,时间复杂度O(sqrt(n) * m),但空间消耗较大

//ErFenTuZuiDaPiPei_dinic
#include<bits/stdc++.h>
#define ll long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define DEBUG cout<<",here\n";
#define MAXN 1205
using namespace std;struct EDGE
{ll c;//capacityll flow;EDGE():c(0),flow(0){}
};EDGE a[MAXN][MAXN];
vector<ll>link[MAXN];
ll ceng[MAXN];ll n,m,s,t,u,v,c,e,maxn,ans=0;ll bfs()//构建层级网络,一次bfs就行了,很简单
{memset(ceng,0,sizeof(ceng));queue<ll>q;q.push(s);ceng[s]=1;while(!q.empty()){ll now=q.front();q.pop();for(auto& i:link[now]){if(ceng[i]==0 && a[now][i].c-a[now][i].flow>0){ceng[i]=ceng[now]+1;q.push(i);}}}if(ceng[t])return 1;//能构建,继续之后的dfsreturn 0;//不能构建更多了,没有更多的增广路了
}//有当前弧优化
ll dfs(ll now,ll minflow)
{if(now==t){ans+=minflow;return minflow;}ll ret=0,minflow2;for(auto& i:link[now]){if(ceng[i]==ceng[now]+1 && a[now][i].c-a[now][i].flow>0){minflow2=dfs(i,min(minflow,a[now][i].c-a[now][i].flow));if(minflow2==0)ceng[i]=0;//debuga[now][i].flow+=minflow2;a[i][now].flow-=minflow2;minflow-=minflow2;//剩余容量减少,以便从该节点直接再往后找增广路,//提高效率,当前弧优化ret+=minflow2;//dfs找到的最小剩余容量之和if(minflow==0)break;}}return ret;//返回从这个节点开始之后找到的所有增广路的流量之和
}int main()
{maxn=pow(2,31);scanf("%lld%lld%lld",&n,&m,&e);for(ll i=1;i<=e;i++){scanf("%lld%lld",&u,&v);v+=n;a[u][v].c+=1;link[u].push_back(v);link[v].push_back(u);}s=0,t=n+m+1;for(ll i=1;i<=n;i++){a[s][i].c+=1;link[s].push_back(i);link[i].push_back(s);}for(ll i=n+1;i<=n+m;i++){a[i][t].c+=1;link[i].push_back(t);link[t].push_back(i);}while(bfs()){dfs(s,maxn);}printf("%lld",ans);return 0;
}

http://chatgpt.dhexx.cn/article/ePjEFJfX.shtml

相关文章

二分图最大匹配与最大独立集

一.概念部分 1.什么是二分图&#xff1f; 通俗的说法&#xff1a;就是可以把图分成两部分&#xff0c;每一部分任意两点之间没有关系&#xff08;同一部落&#xff09;&#xff0c;两部分之间点可能存在多种关系。 2.怎么判断二分图&#xff1f; &#xff08;1&#xff09;…

二分图最大匹配及最大权匹配

二分图最大匹配学习 一.二分图的基本知识二.二分图最大匹配什么是二分图最大匹配怎么求二分图最大匹配 三.二分图最大权匹配四.例题训练三.最小点覆盖数 一位大佬的神级解释 本以为有了网络流&#xff0c;就不用再学匈牙利了&#xff0c;但在做题的过程中&#xff0c;发现有些…

二分图最大匹配问题(匈牙利算法)

什么是二分图 如果一个无向图的的顶点可以分为两个互不相交的子集A和B&#xff0c;那么它就是二分图。也就是说&#xff0c;A、B内部不存在连边&#xff0c;所有连边都一头连着A中的顶点&#xff0c;另一头连着B中的顶点。 什么是二分图最大匹配&#xff1f; 二分图最大匹配…

二分图 二分图最大匹配

首先来说一下什么是二分图。 二分图 二分图又称作二部图&#xff0c;是图论中的一种特殊模型。 设G(V, E)是一个无向图。如果顶点集V可分割为两个互不相交的子集X和Y&#xff0c;并且图中每条边连接的两个顶点一个在X中&#xff0c;另一个在Y中&#xff0c;则称图G为二分图。…

二分图最大匹配(最大流)

先举个例子&#xff0c;有N台计算机和K个任务&#xff0c;每个计算机只能执行一个任务&#xff0c;但可以执行多种任务。现在给出N和K&#xff0c;和其关系&#xff0c;求出最多能处理的任务数。 这就是典型的二分图&#xff0c;整张图被分为两半&#xff0c;一半是电脑&#…

图论总结(一)二分图最大匹配

二分图最大匹配 (一)、二分图 1、定义2、性质3、判定(二)、二分图的匹配 1、二分图的最大匹配2、 Knig定理及其证明3、最小边覆盖与最大独立集(三)、增广路径 1、定义2、性质3、寻找增广路(四)、匈牙利算法 1、找增广路经的算法2、实践3、算法分析(五)、例题 1、最小…

二分图的最大匹配

一、概念&#xff1a; 二分图&#xff1a;简单来说&#xff0c;如果图中点可以被分为两组&#xff0c;并且使得所有边都跨越组的边界&#xff0c;则这就是一个二分图。准确地说&#xff1a;把一个图的顶点划分为两个不相交集 U 和V &#xff0c;使得每一条边都分别连接U、V中的…

二分图最大匹配问题

最近在做的打车项目中&#xff0c;涉及到了用户叫单后&#xff0c;将所有出单司机和所有订单匹配的问题&#xff0c;借此来学习一下二分图的匹配算法。 一、无权二分图最大匹配 首先要区分一下各个概念&#xff1a; 匹配&#xff1a;图G的一个匹配是由一组没有公共端点的不是…

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

二分图最大匹配 &#xff08;一&#xff09;、二分图的介绍1、定义2、充要条件 &#xff08;二&#xff09;、二分图的匹配1、二分图的最大匹配2、增广路径3、匈牙利算法&#xff08;1&#xff09;、复杂度&#xff08;2&#xff09;、算法思路&#xff08;3&#xff09;、代码…

B树最小高度和最大高度的推导

B树最小高度和最大高度的推导 对任意一棵包含n个关键字&#xff0c;高度为h&#xff0c;阶数为m的B树&#xff0c;其最小高度和最大高度的推导过程如下&#xff1a;

算法篇:树之树的高度

算法&#xff1a; 这一类题目很简单&#xff0c;不过却是树的最基本操作之一&#xff0c;引申为判断树是不是平衡二叉树。 一般做法是&#xff0c;计算二叉树的左右子树的高度1&#xff0c;然后取它们的最大值或者最小值。 题目1: https://leetcode-cn.com/problems/balanced-b…

【二叉树】最小高度树

0x00 题目 给定一个 有序 整数数组 元素各不相同且按 升序 排列 编写一个算法&#xff0c;创建一棵 高度最小 的二叉 搜索 树 给定有序数组: [-10,-3,0,5,9] 一个可能的答案是&#xff1a;[0,-3,9,-10,null,5] 它可以表示下面这个高度平衡二叉搜索树&#xff1a; 0 / \ -3 …

常见数据结构详细图解、树的高度、深度、层数、跳表、二叉搜索树、平衡二叉树、红黑树、B树、B+树

常见数据结构 常用的数据结构知识。 1.1 跳表 上图是一个有序链表&#xff0c;我们要检索一个数据就挨个遍历。如果想要再提升查询效率&#xff0c;可以变种为以下结构&#xff1a; 现在&#xff0c;我们要查询11&#xff0c;可以跳着来查询&#xff0c;从而加快查询速度。 …

树的高度 递归法和非递归法

递归法思路&#xff1a; 树的高度即节点子树的高度1&#xff08;节点子树的高度即左子树高度&#xff0c;右子树高度的最大值&#xff09; 代码如下&#xff1a; // Height_Recursive 递归法求树的高度 int Height_Recursive(TreeNode* pTree) {if (pTree NULL) {return 0;…

获取树高度的两种方法与完全二叉树的判断

树的高度 树的高度是节点高度的最大值。 每一层节点的高度如图所示。 方法一&#xff1a;递归 根节点的高度显然就是二叉树的高度。 /** * 获取树的高度* return*/ public int height(){return height2(root); }/*** 使用递归方法获取树的高度* param node* return*/ priv…

红黑树

一.简介 红黑树作为一种二叉搜索树的一种实现&#xff0c;红黑树的左右子树高度差可能大于 1。所以红黑树不是严格意义上的平衡二叉树&#xff08;AVL&#xff09;&#xff0c;但红黑树是黑色节点完美平衡&#xff0c; 其平均统计性能要强于 AVL 。 红黑树是每个节点都带有颜…

B树最大高度推导

文章目录 B树最大高度推导推导B树的最小高度推导最大高度 B树&#xff1a;MySQL数据库索引是如何实现的&#xff1f;1. 遇到问题2. 尝试用学过的数据结构解决这个问题3. 改造二叉查找树4. 索引的弊端 B树最大高度推导 【声明几个重要概念】 B树的关键字就是要查找的东西 B树…

红黑树详解

1&#xff0c;红黑树特点 每一个结点都有颜色&#xff0c;要么红色&#xff0c;要么黑色。根结点必须是黑色的。红色结点的子结点必须是黑色的。任何一个结点&#xff0c;到它所有叶子结点&#xff0c;经过相同个数的黑色结点。&#xff08;红黑树的平衡含义&#xff0c;左右高…

MYSQL的B+Tree索引树高度如何计算

我们使用MySQL数据库的时候&#xff0c;绝大部分的情况下在使用InnoDB存储引擎&#xff0c;偶尔会使用MyISAM存储引擎&#xff0c;至于其他存储引擎&#xff0c;我相信大家都很少接触到&#xff0c;甚至可能都没有听说过。所以本文只讲解InnoDB和MyISAM两个存储引擎的索引&…

红黑树高度上限的证明(通俗易懂)

先把结论放上&#xff0c;设红黑树的高度为h&#xff0c;总结点数为n&#xff0c;那么h与n的关系就是 下面开始证明过程 首先&#xff0c;从任意节点出发&#xff0c;到其子树的叶子节点的路径中黑色节点的数量称为该节点的黑高&#xff0c;即 bh 我们设根节点为T,那么根节点…