二分图是图,可以用图的数据结构存储二分图,邻接矩阵和邻接表
二分图的特点是,图的顶点可以分为两组,两组组内的节点之间没有连接,所有的连接都是在两组之间的。
所谓一个匹配是两组节点一对一的连接。
二分图的最大匹配所要完成的一个任务是在一个二分图中找出最多的匹配数。
二分图最大匹配匈牙利算法的核心在于新增加的一对匹配能否成功的加入到结果集当中去。
能够成功加入分为两种情况
情况1.右侧的节点还没有连接
情况2.如果右侧的节点已经连接,通过调整右侧节点连接的左节点,将右侧节点空出来。(这是一个递归的过程)
为什么在为左边的每一个顶点匹配是都要重置数组?
防止上一轮的遍历对当前造成影响。实际上标记vis数组的过程就是情况2的调整过程。
每一轮的调整都是独立的。
代码模板
hdu2063
- /*
- 匈牙利算法解决二分图最大匹配问题
- 采用的邻接矩阵的形式,g[i][j]
- maxn代表一边最多的顶点数,un代表左边顶点数,vn代表右边顶点数
- linked[i]代表右边的第i个点与左边哪个点相匹配
- */
- #include <iostream>
- #include <stdio.h>
- #include <algorithm>
- #include <string.h>
- using namespace std;
- const int maxn=502;
- int un,vn;//左边顶点数,右边顶点数
- int g[maxn][maxn];//邻接矩阵来存储边
- int linked[maxn];//右边的点和左边的哪个点匹配
- bool vis[maxn];
- bool dfs(int u)
- {
- for(int v=1;v<=vn;v++)//遍历右边顶点
- {
- if(g[u][v]&&!vis[v])
- {
- vis[v]=1;
- if(!linked[v]||dfs(linked[v]))//右边顶点还没有被匹配,或者已经匹配的前面左边顶点可以去寻找另一个匹配而把该右边顶点“腾出空位”让给当前左边顶点u
- {
- linked[v]=u;
- return true;
- }
- }
- }
- return false;
- }
- int hungary()
- {
- int ans=0;
- memset(linked,0,sizeof(linked));
- for(int u=1;u<=un;u++)//遍历左边顶点,去寻找与之匹配的右边顶点
- {
- memset(vis,0,sizeof(vis));
- if(dfs(u))//去找u能不能匹配,如果可以匹配的话,ans++
- ans++;
- }
- return ans;
- }
- int k,m,n;//m为题目中要求输入的左边顶点数,n为题目中要求输入的右边顶点数
- int main()
- {
- while(scanf("%d",&k)!=EOF&&k)
- {
- scanf("%d%d",&m,&n);
- un=m;vn=n;
- memset(g,0,sizeof(g));
- int u,v;
- for(int i=1;i<=k;i++)
- {
- scanf("%d%d",&u,&v);//u和v有边
- g[u][v]=1;
- }
- printf("%d\n",hungary());
- }
- return 0;
- }
http://blog.csdn.net/sr_19930829/article/details/41843563
http://blog.csdn.net/dark_scope/article/details/8880547
我表示我真是什么都不懂的小白。。下面是以为大神的关于二分图的讲解,非常详细,码一下
http://blog.csdn.net/sixdaycoder/article/details/47680831