二分图多重匹配

合集下载

图论中的二分图匹配问题及其算法设计思路

图论中的二分图匹配问题及其算法设计思路

图论中的二分图匹配问题及其算法设计思路图论是数学中一个重要的分支,研究图的性质和结构,以及解决与图相关的问题。

其中,二分图匹配问题是图论中的经典问题之一。

本文将介绍二分图匹配问题的定义、特性,并讨论相关的算法设计思路。

一、二分图匹配问题的定义二分图是一种特殊的图结构,其中的顶点可以分为两个互不相交的集合,且每条边都只连接两个集合之间的顶点。

对于一个二分图,如果存在一种边的划分方式,使得每个顶点都与边集中的一条边相连,那么我们称这个边集为二分图的一个匹配。

二分图匹配问题的目标是寻找出一个匹配,使得匹配的边数最大。

这个问题在实际应用中有许多场景,比如婚姻匹配、求职配对等。

为了解决这个问题,人们提出了多种算法,下面将介绍其中两个常用的算法。

二、匈牙利算法匈牙利算法是用于求解二分图最大匹配的一种经典算法,它基于深度优先搜索的思想。

算法的基本思路是从一个没有匹配边的顶点开始,逐个尝试与其相连的顶点进行匹配,如果能成功匹配则将边加入匹配集合中,如果不能成功匹配则继续尝试下一个顶点。

当所有的顶点都尝试过后,即得到一个最大匹配。

以下是匈牙利算法的伪代码:1. 初始化匹配集合为空2. 从一个未匹配的顶点开始,对其进行深度优先搜索3. 如果找到了增广路径,则更新匹配集合4. 重复步骤2和3,直到无法找到增广路径5. 返回最大匹配匈牙利算法的时间复杂度为O(V*E),其中V表示顶点数,E表示边数。

虽然算法的时间复杂度较高,但它在实际应用中仍然具有一定的效率和适用性。

三、Hopcroft-Karp算法Hopcroft-Karp算法是用于求解二分图最大匹配的另一种算法,它是对匈牙利算法的改进和优化。

Hopcroft-Karp算法的核心思想是通过多次的广度优先搜索来寻找增广路径,从而提高算法的效率。

以下是Hopcroft-Karp算法的伪代码:1. 初始化匹配集合为空2. 初始化标记集合为空3. 利用广度优先搜索寻找增广路径4. 如果找到增广路径,则更新匹配集合5. 重复步骤3和4,直到无法找到增广路径6. 返回最大匹配Hopcroft-Karp算法的时间复杂度为O(E*sqrt(V)),相比于匈牙利算法有较大的优势。

图匹配总结二分图匹配

图匹配总结二分图匹配

序言:回忆起最初学习图匹配算法的艰辛与困惑,苦中有乐,但很多时间都浪费在了资料的寻找与甄别上。

因此,在对自己做一次知识总结的同时,整理与记录下了这些文字,希望能够给大家带来一定的帮助。

目录:第一部分:二分图的最大匹配第二部分:五种方式,两类构图第三部分:二分图匹配算法总结第四部分:二分图的最优权值匹配第五部分:一般图的最大匹配第六部分:图匹配题目列表符号说明:N,V:点数E:边数u,v,i,j:节点的标号INF:正无穷大-INF:负无穷大名词说明:时间复杂度:算法的理论时间上界时间效率:实际中算法运行的平均时间效率引用说明:文中参考了一些来源于网络的资料,也有原文全段引用的部分。

在这些资料被n+1次转载后,我已无法获知所有原作者的信息。

在此,对所有前辈们表示真诚的歉意和诚挚的敬意。

特别感谢Amber大神犀利的代码。

作者:Snow_storm正文:第一部分:二分图匹配有这么两个奇怪的工厂:工厂X只生产杯具,工厂Y只生产洗具。

最近,两个工厂决定将产品实行打包策略:即一个杯具搭配上一个洗具。

但由于杯具和洗具的形状和功能各不相同,对于某个类别的杯具来说,只能搭配某些类型的洗具。

现在,两个工厂的厂长大人想知道最多能成功的搭配多少对杯具与洗具。

类似于上面例子中提到的搭配问题,在图论中的有规范的名称:匹配。

注意到,上面的例子中涉及到的物品只有两类(杯具与洗具),且问题只涉及杯具与洗具的匹配,我们把这种只涉及一种关系的匹配问题称为二分匹配问题。

现在,让我们理清一些概念。

二分图:若图G中的点可以分为X和Y两部分,且每部分内部无任何边相连,则称图G为二分图。

匹配:无公共点的边集合(可以想象一下结婚这个词汇)。

匹配数:边集中边的个数最大匹配:匹配数最大的匹配。

如图1-1,展示的就是一个二分图:粗体线表示该二分图的一种匹配方式,不难发现,此时的匹配已经是最大匹配。

图 1-1如何能得到一个二分图的最大匹配?运用简单的枚举:找出全部匹配,然后保留匹配数最多的。

图论:二分图多重匹配

图论:二分图多重匹配

图论:⼆分图多重匹配使⽤最⼤流和费⽤流解决⼆分图的多重匹配之前编辑的忘存了好⽓啊。

本来打算学完⼆分图的乱七⼋糟的匹配之后再去接触⽹络流的,提前撞到了之前我们说的⼆分图最⼤匹配和⼆分图最⼤权匹配有⼀个特点,那就是没个点只能与⼀条边相匹配如果规定⼀个点要与L条边相匹配,这样的问题就是⼆分图的多重匹配问题然后根据边是否带权重,⼜可以分为⼆分图最⼤多重匹配和⼆分图最⼤权多重匹配(⼆分图多重最佳完美匹配)⾸先给出⼆分图多重最⼤匹配的做法:在原图上建⽴源点S和汇点T,S向每个X⽅点连⼀条容量为该X⽅点L值的边,每个Y⽅点向T连⼀条容量为该Y⽅点L值的边原来⼆分图中各边在新的⽹络中仍存在,容量为1(若该边可以使⽤多次则容量⼤于1),求该⽹络的最⼤流,就是该⼆分图多重最⼤匹配的值然后给出⼆分图多重最优匹配(⼆分图多重最⼤权匹配)的做法:在原图上建⽴源点S和汇点T,S向每个X⽅点连⼀条容量为该X⽅点L值、费⽤为0的边,每个Y⽅点向T连⼀条容量为该Y⽅点L值、费⽤为0的边原来⼆分图中各边在新的⽹络中仍存在,容量为1(若该边可以使⽤多次则容量⼤于1),费⽤为该边的权值。

求该⽹络的最⼤费⽤最⼤流,就是该⼆分图多重最优匹配的值这道题⾥⾯,⼀共有X⽅点这么多的电影,每个电影需要拍摄多少天就是对应的X⽅点L值,然后每⼀天是⼀个Y⽅点,由于每⼀天只能拍摄⼀部电影,所有Y⽅点的L值均为1下⾯介绍⼀下实现:int n,sum,cnt,ans;int g[maxn],cur[maxn];int str[25][10];struct Edge{int u,v,next,cap,flow;}e[maxm];这⾥⾯的cur数组是g数组的临时数组str⽤来保存每⼀个电影可以在哪⼀天拍摄Edge是⽹络流图⾥⾯的边void addedge(int u,int v,int c){e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=c;e[cnt].flow=0;e[cnt].next=g[u];g[u]=cnt;e[++cnt].u=v;e[cnt].v=u;e[cnt].cap=0;e[cnt].flow=0;e[cnt].next=g[v];g[v]=cnt;}建图的时候,注意怎么赋值的接下来根据题意建图:for(int i=1;i<=n;i++){for(int j=1;j<=7;j++)scanf("%d",&str[i][j]);scanf("%d%d",&d,&w);sum+=d;addedge(0,i,d); //容量为需要多少天for(int j=1;j<=7;j++)for(int k=0;k<w;k++)if(str[i][j]) addedge(i,20+k*7+j,1);}for(int i=21;i<=370;i++) addedge(i,371,1);ans=maxflow(0,371);0为源点,371为汇点sum最后进⾏⼀个统计,和源点出发的最⼤流量进⾏⽐较,如果相等,说明电影排的开然后是求最⼤流的⼀个板⼦int maxflow(int st,int ed){int flowsum=0;while(bfs(st,ed)){memcpy(cur,g,sizeof(g));flowsum+=dfs(st,ed,INF);//cout<<"#"<<flowsum<<" ";}return flowsum;}具体的DFS和BFS这⾥不作为重点,以后再说下⾯给出完整的实现:1 #include<cstdio>2 #include<cstring>3 #include<algorithm>4using namespace std;5const int INF=1000000000;6const int maxn=1005;7const int maxm=20005;8int n,sum,cnt,ans;9int g[maxn],cur[maxn];10int str[25][10];11struct Edge{int u,v,next,cap,flow;}e[maxm];12void addedge(int u,int v,int c)13 {14 e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=c;15 e[cnt].flow=0;e[cnt].next=g[u];g[u]=cnt;1617 e[++cnt].u=v;e[cnt].v=u;e[cnt].cap=0;18 e[cnt].flow=0;e[cnt].next=g[v];g[v]=cnt;19 }20int q[maxn],vis[maxn],d[maxn];21bool bfs(int st,int ed)22 {23 memset(q,0,sizeof(q));24 memset(vis,0,sizeof(vis));25 memset(d,-1,sizeof(d));26 vis[st]=1;d[st]=0;27int h=0,t=1;28 q[t]=st;29while(h!=t)30 {31 h=h%maxn+1;32int u=q[h];33for(int tmp=g[u];tmp;tmp=e[tmp].next)34 {35if(!vis[e[tmp].v]&&e[tmp].cap>e[tmp].flow)36 {37 vis[e[tmp].v]=1;38 d[e[tmp].v]=d[u]+1;39if(e[tmp].v==ed) return true;40 t=t%maxn+1;41 q[t]=e[tmp].v;42 }43 }44 }45return false;46 }47int getpair(int x)48 {49if(x%2==0)50return x-1;51else return x+1;52 }53int dfs(int x,int ed,int a)54 {55if(x==ed||a==0) return a;56int flow=0,f;57for(int tmp=cur[x];tmp;tmp=e[tmp].next)58 {59if(d[e[tmp].v]==d[x]+1&&(f=dfs(e[tmp].v,ed,min(a,e[tmp].cap-e[tmp].flow)))>0)60 {61 e[tmp].flow+=f;62 e[getpair(tmp)].flow-=f;63 a-=f;64 flow+=f;65if(a==0) break;66 }67 }68return flow;69 }70int maxflow(int st,int ed)71 {72int flowsum=0;73while(bfs(st,ed))74 {75 memcpy(cur,g,sizeof(g));76 flowsum+=dfs(st,ed,INF);77//cout<<"#"<<flowsum<<" ";78 }79return flowsum;8081 }82void init()83 {84 sum=cnt=0;85 memset(g,0,sizeof(g));86 }87int main()88 {89int T,d,w;90 scanf("%d",&T);91while(T--)92 {93 init();94 scanf("%d",&n);95for(int i=1;i<=n;i++)96 {97for(int j=1;j<=7;j++)98 scanf("%d",&str[i][j]);99 scanf("%d%d",&d,&w);100 sum+=d;101 addedge(0,i,d); //容量为需要多少天102for(int j=1;j<=7;j++)103for(int k=0;k<w;k++)104if(str[i][j]) addedge(i,20+k*7+j,1);105 }106for(int i=21;i<=370;i++) addedge(i,371,1);107 ans=maxflow(0,371);108if(ans==sum) printf("Yes\n");109else printf("No\n");110 }111return0;112 }据说这是典型的最⼤流题⽬,然⽽为了强⾏安利⼀波⼆分图的多重匹配,就不说成那个了。

第九讲 二分图匹配问题(1)

第九讲   二分图匹配问题(1)

第九讲二分图匹配问题一、问题设G=(V,{R})是一个无向图。

如顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属两个不同的子集。

则称图G为二分图。

给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

选择这样的边数最大的子集称为图的最大匹配问题(maximal matching problem)如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。

最大匹配在实际中有广泛的用处,求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。

即回溯法,但是这个算法的复杂度为边数的指数级函数。

因此,需要寻求一种更加高效的算法。

二、算法分析二分图的最大匹配有2种实现,网络流和匈牙利算法。

1.匈牙利算法是求解最大匹配的有效算法,该算法用到了增广路的定义(也称增广轨或交错轨):若边集合P 是图G中一条连通两个未匹配顶点的路径,并且属M的边和不属M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。

2.由增广路径的定义可以推出下述三个结论:(1). P的路径长度必定为奇数,第一条边和最后一条边都不属于M。

(2). P经过“取反操作”(即非M中的边变为M中的边,原来M中的边去掉)可以得到一个更大的匹配M’。

(3). M为G的最大匹配当且仅当不存在相对于M的增广路径。

3.从而可以得到求解最大匹配的匈牙利算法:(1)置M为空;(2)找出一条增广路径P,通过“取反操作”获得更大的匹配M’代替M;(3)重复(2)操作直到找不出增广路径为止;根据该算法,可以选择深搜或者广搜实现,下面给出易于实现的深度优先搜索(DFS)实现。

三、实现1. 匈牙利算法的算法轮廓bool寻找从k出发的对应项出的可增广路{while(j与k邻接){if(j不在增广路上){把j加入增广路;if(j是未盖点或者从j的对应项出发有可增广路)则从k的对应项出有可增广路,返回true;修改j的对应项为k;}}从k的对应项出没有可增广路,返回false;}2. 匈牙利算法流程3.代码int n, m, match[100]; //二分图的两个集合分别含有n和m个元素,match[i]存储集合m中的节点i在集合n 中的匹配节点,初值为-1。

二分图匹配问题最大匹配以及相关结论多重匹配最大带权匹配带花树算法

二分图匹配问题最大匹配以及相关结论多重匹配最大带权匹配带花树算法

⼆分图匹配问题最⼤匹配以及相关结论多重匹配最⼤带权匹配带花树算法⼆分图匹配问题:做法:①匈⽛利算法,时间复杂度O(N*V)②Hopcroft-Karp,时间复杂度O(√N*V)相关结论:①最⼩顶点覆盖(könig定理) ⼆分图的最⼩顶点覆盖=最⼤匹配数②最⼩路径覆盖(不要求⼆分图):在图中找⼀些路径,使之覆盖了图中的所有顶点,且任何⼀个顶点有且只有⼀条路径与之关 最⼩路径覆盖 = 顶点数 - 最⼤匹配配对于有向⽆环图,⾸先拆点,建成⼆分图再进⾏求解·最⼩不相交路径覆盖 建图⽅式:把⼀个的点V拆点成Vx和Vy,如果A连向B,那么就建⼀条Ax连向By的边。

 图中有多少条路径,可以以⼀种⽅法得到,就是计算出度为0的点的个数。

如果知道这个就很容易得出这个结论了 ·最⼩相交路径覆盖 做法⾸先跑floyd,求出原图的传递闭包,然后⽤上述⽅法做即可③最⼩边覆盖最⼩边覆盖=图顶点-最⼤匹配⾸先⼀开始,假如⼀条边都不选的话,要覆盖所有的点就必须每个点都选⼀次,也就是n次,然后每选⼀条边就会减少1个,所以结论显⽽易见④最⼤独⽴集最⼤独⽴集=图顶点-最⼤匹配=最⼩边覆盖⼆分图的独⽴数等于顶点数减去最⼤匹配数,很显然的把最⼤匹配两端的点都从顶点集中去掉这个时候剩余的点是独⽴集,这是|V|-2*|M|,同时必然可以从每条匹配边的两端取⼀个点加⼊独⽴集并且保持其独⽴集性质。

⼆分图多重匹配( ⼀ ) 如果x部节点只对应⼀个y部节点,⽽y部节点可以对应多个x部节点,那么这种匹配可以⽤匈⽛利算法来解决解决的问题:⼀个y最多匹配cnt个x是否成⽴,要问⼀个y匹配⼈数最⼤的最⼩值可以⽤⼆分答案来做解决思路:根据匈⽛利算法的思想,这时的link[u]要变成link[u][i],表⽰与y[u]匹配好了的第i个点,⽤vlink[u]记录已经于u点匹配了的点的个数,对于x中的x[k],找到⼀个与他相连的y[i]后,同样判断匈⽛利算法中的两个条件是否成⽴,若满⾜第⼀个条件,直接将x[k],y[i]匹配,否则,如果与y[i]所匹配的点已经达到了饱和,那么在所有与y[i]配合的点中选⼀个点,检查能否找到增⼴路,如果能,就让出位置让x[k]与y[i]匹配( ⼆ )如果x部节点可以匹配多个y部节点,y部节点可以同时匹配多个x部节点,那么应该⽤⽹络流来解决。

二分图匹最大配与最佳匹配

二分图匹最大配与最佳匹配

二分图:二分图是这样的一个图,它的顶点可以分为两个集合X和Y。

所有的边关联的两个顶点中,恰好一个属于集合X,一个属于集合Y。

二分图的匹配:给定一个二分图G,M为G边集的一个子集,如果M满足当中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

二分图的最大匹配:二分图的所有匹配中包含边数最多的匹配称为图的最大匹配。

完美(完备)匹配:如果所有点都在匹配边上,称这个最大匹配是完美匹配。

最佳匹配:如果边上带权的话,找出权和最大的匹配叫做求最佳匹配。

增广路径:也称增广轨或交错轨。

若P是图G中一条连通两个未匹配顶点的路径,并且属最大匹配边集M的边和不属M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广轨。

定义总是抽象的下面通过图来理解它。

图中的线段(2->3, 3->1, 1->4)便是上面所说的p路径,我们假定边(1,3)是以匹配的边,(2,3)(1,4)是未匹配的边,则边(4,1)边(1,3)和边(3,2)在路径p上交替的出现啦,那么p就是相对于M的一条增广轨,这样我们就可以用边1,4 和边2,3 来替换边1,3 那么以匹配的边集数量就可以加1,。

下面给出关于二分图最大匹配的三个定理1:最大匹配数+ 最大独立集= n + m2:二分图的最小覆盖数= 最大匹配数3:最小路径覆盖= 最大独立集最大独立集是指求一个二分图中最大的一个点集,该点集内的点互不相连。

最小顶点覆盖是指在二分图中,用最少的点,让所有的边至少和一个点有关联。

最小路径覆盖是指一个不含圈的有向图G 中,G的一个路径覆盖是一个其结点不相交的路径集合P,图中的每一个结点仅包含于P 中的某一条路径。

路径可以从任意结点开始和结束,且长度也为任意值,包括0.1求解二分图最大匹配的方法:●匈牙利算法(时间复杂度O(nm))其思想是是通过不断的寻找增广轨实现最大匹配。

●转化为单位容量简单网络的最大流问题(本文不介绍)在二分图的基础上,加入源点s和汇点t,让s与每个X结点连一条边,每个Y结点和t连一条边,所有弧的容量为1。

算法学习:图论之二分图的最优匹配(KM算法)

算法学习:图论之二分图的最优匹配(KM算法)

二分图的最优匹配(KM算法)KM算法用来解决最大权匹配问题:在一个二分图内,左顶点为X,右顶点为Y,现对于每组左右连接XiYj有权wij,求一种匹配使得所有wij的和最大。

基本原理该算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。

设顶点Xi的顶标为A[ i ],顶点Yj的顶标为B[ j ],顶点Xi与Yj之间的边权为w[i,j]。

在算法执行过程中的任一时刻,对于任一条边(i,j),A[ i ]+B[j]>=w[i,j]始终成立。

KM算法的正确性基于以下定理:若由二分图中所有满足A[ i ]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。

首先解释下什么是完备匹配,所谓的完备匹配就是在二部图中,X点集中的所有点都有对应的匹配或者是Y点集中所有的点都有对应的匹配,则称该匹配为完备匹配。

这个定理是显然的。

因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和。

所以相等子图的完备匹配一定是二分图的最大权匹配。

初始时为了使A[ i ]+B[j]>=w[i,j]恒成立,令A[ i ]为所有与顶点Xi关联的边的最大权,B[j]=0。

如果当前的相等子图没有完备匹配,就按下面的方法修改顶标以使扩大相等子图,直到相等子图具有完备匹配为止。

我们求当前相等子图的完备匹配失败了,是因为对于某个X顶点,我们找不到一条从它出发的交错路。

这时我们获得了一棵交错树,它的叶子结点全部是X顶点。

现在我们把交错树中X顶点的顶标全都减小某个值d,Y顶点的顶标全都增加同一个值d,那么我们会发现:1)两端都在交错树中的边(i,j),A[ i ]+B[j]的值没有变化。

也就是说,它原来属于相等子图,现在仍属于相等子图。

2)两端都不在交错树中的边(i,j),A[ i ]和B[j]都没有变化。

图论中的二分图匹配问题及其算法设计思路

图论中的二分图匹配问题及其算法设计思路

图论中的二分图匹配问题及其算法设计思路二分图匹配问题是图论中的重要问题之一。

二分图是指一个图的顶点可以分为两个互斥的集合,并且图的边只能连接两个集合之间的顶点。

二分图匹配的目标是找到一个匹配,即找到一种对应关系,使得图中的所有顶点都能够与另一个集合中的顶点相连。

在实际应用中,二分图匹配有着广泛的应用。

比如在招聘网站中,求职者和企业可以被看作是一个二分图,通过匹配求职者和企业,可以使得求职者找到合适的工作岗位,企业找到合适的人才。

在网络流量调度中,可以将网络中的节点和链路看作一个二分图,通过匹配可以实现有效的数据传输。

那么如何解决二分图匹配问题呢?目前比较常用的算法有匈牙利算法和增广路径算法。

匈牙利算法,也称为增广路径算法,是解决二分图最大匹配问题的一种经典算法。

该算法从某一个未匹配的顶点开始,尝试去匹配其他的顶点。

如果当前顶点没有匹配的边,那么匈牙利算法会尝试寻找一个增广路径,即一条能够增加匹配数的路径。

当不存在增广路径时,匈牙利算法会返回当前匹配的结果。

增广路径算法是一个递归的过程。

首先,我们从一个未匹配的顶点开始,将其标记为已访问。

然后遍历与该顶点相连的所有边,如果边的另一个顶点没有被访问过,那么我们尝试去匹配这个顶点。

如果匹配成功,那么整个算法就结束了,返回当前的匹配结果。

如果匹配失败,我们需要尝试寻找另一个增广路径,这时我们会递归地调用增广路径算法,从当前的匹配边的另一个顶点开始。

增广路径算法的时间复杂度为O(V*E),其中V是顶点数,E是边数。

在实际应用中,匈牙利算法已经被广泛应用,因为其算法简单易懂,同时具有较好的计算效率。

除了匈牙利算法,还有其他一些解决二分图匹配问题的算法,比如多项式时间的Hopcroft-Karp算法和Edmonds的算法。

这些算法在不同的应用场景中,可能有着更好的性能表现。

总结来说,二分图匹配问题在图论中具有重要的地位,它可以通过匈牙利算法等多种算法来解决。

在实际应用中,二分图匹配问题可以用于求职招聘、网络流量调度等领域。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二分图多重匹配问题
多重匹配是建立在单重匹配的基础上的,我们先回顾下单重匹配的时候,我们用一个数组cm[i]来表示与i匹配的点,而多重匹配的时候我们用的是一个结构体:
struct p
{
int girl[MAXN],num;
}cm[MAXN];
其中cm[i].num代表当前已经有多少个与i进行匹配了,与之匹配的点保存在cm[i].girl[]中。

还有一个不同的地方是在找增广路的时候,单重匹配是直接判断cm[i]是否等于-1,即是否已经匹配过,如果没匹配过则找增广路结束,否则沿着cm[i]继续找增广路。

多重匹配也是相似的方法,如果与cm[i]匹配的个数少于最大可匹配数的时候,同样找增广路结束,否则沿着所以与cm[i]匹配的点继续找增广路,只要其中有一个点找到了增广路就可以了。

关键代码如下:
if(cm[i].num<dm[i])
{
cm[i].girl[cm[i].num++]=t;
//cn[t]=i;
return 1;
}
else
for(j=0;j<cm[i].num;j++)
if(dfs(cm[i].girl[j]))
{
cm[i].girl[j]=t;
//cn[t]=i;
return 1;
}
当然,也可以拆点然后用一般的二分图匹配来做。

2. 最大流
此题如果用最大流算法做的话,建图非常简单,直接添加源点S和汇点T,对于每一个MM i连一条Sài,容量为1,对于每一个GG j,连一条jàT,容量为cj,如果GG j想要包养MM i,则连一个iàj,容量为INF的边。

然后从S到T求一次最大流,最大流值就是所求的答案(证明略)。

相关文档
最新文档