二分图匹配之最佳匹配——KM算法
2017-01-16 22:13
169 查看
今天也大致学了下KM算法,用于求二分图匹配的最佳匹配。
何为最佳?我们能用匈牙利算法对二分图进行最大匹配,但匹配的方式不唯一,如果我们假设每条边有权值,那么一定会存在一个最大权值的匹配情况,但对于KM算法的话这个情况有点特殊,这个匹配情况是要在完全匹配(就是各个点都能一一对应另一个点)情况下的前提。
自然,KM算法跟匈牙利算法有相似之处。
其算法步骤如下:
1.用邻接矩阵(或其他方法也行啦)来储存图,注意:如果只是想求最大权值匹配而不要求是完全匹配的话,请把各个不相连的边的权值设置为0。
2.运用贪心算法初始化标杆。
3.运用匈牙利算法找到完备匹配。
4.如果找不到,则通过修改标杆,增加一些边。
5.重复3,4的步骤,直到完全匹配时可结束。
一言不合地冒出了个标杆??标杆是什么???
在解释这个问题之前,我们先来假设一个很简单的情况,用我们人类伟大的智能思维去思考思考。
KM算法
何为最佳?我们能用匈牙利算法对二分图进行最大匹配,但匹配的方式不唯一,如果我们假设每条边有权值,那么一定会存在一个最大权值的匹配情况,但对于KM算法的话这个情况有点特殊,这个匹配情况是要在完全匹配(就是各个点都能一一对应另一个点)情况下的前提。
自然,KM算法跟匈牙利算法有相似之处。
其算法步骤如下:
1.用邻接矩阵(或其他方法也行啦)来储存图,注意:如果只是想求最大权值匹配而不要求是完全匹配的话,请把各个不相连的边的权值设置为0。
2.运用贪心算法初始化标杆。
3.运用匈牙利算法找到完备匹配。
4.如果找不到,则通过修改标杆,增加一些边。
5.重复3,4的步骤,直到完全匹配时可结束。
一言不合地冒出了个标杆??标杆是什么???
在解释这个问题之前,我们先来假设一个很简单的情况,用我们人类伟大的智能思维去思考思考。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int qwq=0x7fffffff; int w[1000][1000]; //w数组记录边权值 int line[1000],usex[1000],usey[1000],cx[1000],cy[1000]; //line数组记录右边端点所连的左端点, usex,usey数组记录是否曾访问过,也是判断是否在增广路上,cx,cy数组就是记录点的顶标 int n,ans,m; //n左m右 bool find(int x){ usex[x]=1; for (int i=1;i<=m;i++){ if ((usey[i]==0)&&(cx[x]+cy[i]==w[x][i])){ //如果这个点未访问过并且它是子图里面的边 usey[i]=1; if ((line[i]==0)||find(line[i])){ //如果这个点未匹配或者匹配点能更改 line[i]=x; return true; } } } return false; } int km(){ for (int i=1;i<=n;i++){ //分别对左边点依次匹配 while (true){ int d=qwq; memset(usex,0,sizeof(usex)); memset(usey,0,sizeof(usey)); if (find(i)) break; //直到成功匹配才换下一个点匹配 for (int j=1;j<=n;j++) if (usex[j]) for (int k=1;k<=m;k++) if (!usey[k]) d=min(d,cx[j]+cy[k]-w[j][k]); //计算d值 if (d==qwq) return -1; for (int j=1;j<=n;j++) if (usex[j]) cx[j]-=d; for (int j=1;j<=m;j++) if (usey[j]) cy[j]+=d; //添加新边 } } ans=0; for (int i=1;i<=m;i++) ans+=w[line[i]][i]; return ans; } int main(){ while (~scanf("%d%d",&n,&m)){ memset(cy,0,sizeof(cy)); memset(w,0,sizeof(w)); memset(cx,0,sizeof(cx)); for (int i=1;i<=n;i++){ int d=0; for (int j=1;j<=n;j++){ scanf("%d",&w[i][j]); d=max(d,w[i][j]); //此处顺便初始化左边点的顶标 } cx[i]=d; } memset(line,0,sizeof(line)); printf("%d\n",km()); } return 0; }
KM算法
相关文章推荐
- 基础知识(11) -- 二叉树
- 2017.1.16——寒假集训第四天
- 9.Handler消息机制
- 396. Rotate Function*
- InstantObjects是delphi上的一个不错的ORM框架,可以实现类似hibernate的功能。
- solr集群搭建
- (转)Android Handler 主线程 子线程 双向通信
- 弹飞绵羊(bzoj 2002)
- POJ1459Power Network(最大流)
- 万物简史
- Windows下自启动程序管理
- errorlevel 续1
- 操作系统之 用户级线程与内核级线程
- win7装虚拟机(VMware,ubantu)
- 黑苹果MAC好处与坏处
- 用二进制位运算 来判断一个数是奇数还是偶数
- android树形列表实现
- 3252: 攻略
- 洛谷比赛『期末考后的休闲比赛2』
- 8.版本控制svn和git