KM算法(二分图的最佳完美匹配)
KM算法大概过程:
(1)初始化Lx数组为该boy的一条权值最大的出边。初始化Ly数组为 0。
(2)对于每个boy,用DFS为其找到一个girl对象,顺路记录下S和T集,并更新每个girl的slack值。若不能为其找到对象,则转3。
(3)找出非T集合的girl的最小slack值为d,更新S集中的boy和T集中的girl,并且顺路更新非T集中的slack值。对于那个失败的boy继续第2步。
简括之,就是在保持当前权和最高的情况下,尽量为每个boy找到权更大的边。找的过程就是DFS过程,标记出S和T集是为了保证权和最大,因为只要帮S中任意一个boy另找一个女对象,为这个boy的此次脱单之路告终。
DFS的要完成的任务:
(1)标记S和T集。
(2)更新每个girl的slack值为最小。
模板还是必须的,带满了注释,改自kuangbin的模板。
/* KM算法:复杂度O(nx*nx*ny)
* 完全二分图求最大权匹配(必须为所有boy找到对象,且boy数量必须<=girl数量)
* 若求最小权匹配,可将权值取相反数,结果取相反数
* 点的编号从1开始。
* 以男女模型出现比较直观。
*/
int nx, ny; //两边的点数,x为男,y为女。
int g[N][N]; //二分图描述,g[x][y]表示边权。
int girl[N], Lx[N], Ly[N]; //girl[i]记录i的匹配成功对象,男女的顶标
int slack[N]; //为了优化用的,连接到对应girl的松弛值。
bool S[N], T[N]; //匈牙利树的节点集合,S为男,T为女。 bool DFS(int x) // x一定是boy
{
S[x]=true;
for(int i=; i<=ny; i++) //枚举girl
{
if(T[i]) continue;
int tmp=Lx[x]+Ly[i]-g[x][i];
if( tmp== )
{
T[i]=true;
//为第i个girl的男对象另找女对象
if(girl[i]==- || DFS(girl[i]))
{
girl[i]=x; //记录匹配的boy
return true;
}
}
else if(slack[i]>tmp) //顺便更新下slack
slack[i]=tmp;
}
return false;
} int KM()
{
memset(girl, -, sizeof(girl));
memset(Ly, , sizeof(Ly));
for(int i=; i<=nx; i++) //初始化两个L数组分别为-INF和0
{
Lx[i] = -INF;
for(int j=; j<=ny; j++)
if(g[i][j]>Lx[i]) Lx[i]=g[i][j];
}
for(int j=; j<=nx; j++) //枚举boy
{
for(int i=; i<=ny; i++) //初始slack为无穷。slack只需要记录girl的。
slack[i]=INF;
while(true) //无限循环,直到帮boy[j]找到对象
{
memset(S, , sizeof(S));
memset(T, , sizeof(T));
if( DFS(j) ) break; //直接就找到对象了,搞定。
int d=INF;
for(int i=; i<=ny; i++) //根据不在匈牙利树上的girl的slack值找到最小值d
if(!T[i] && d>slack[i])
d=slack[i];
for(int i=; i<=nx; i++) //所有匈牙利树上的boy更新lx值
if(S[i]) Lx[i]-=d;
for(int i=; i<=ny; i++) //树上的girl加d,不在树上的girl的slack减d。
{
if(T[i]) Ly[i]+=d; //这是为了让等式仍然成立
else slack[i]-=d;
}
}
}
int ans=;
for(int i=; i<=ny; i++) //累计匹配边的权和
if(girl[i]>) ans+=g[girl[i]][i];
return ans;
}
KM算法
KM算法(二分图的最佳完美匹配)的更多相关文章
- 二分图学习记 之 KM算法 二分图最大权完美匹配。
前置知识 :匈牙利算法 首先有这样一张图,求这张图的最大权完美匹配. 当然如果你不想看这些渣图的话,您可以转到 洛谷 运动员最佳匹配问题 下面我来强行解释一下KM算法 左边一群妹子找汉子,但是每个妹子 ...
- hdu1533 Going Home km算法解决最小权完美匹配
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
- HDU 2255 KM算法 二分图最大权值匹配
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)
UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...
- 【模板】二分图最大权完美匹配KM算法
hdu2255模板题 KM是什么意思,详见百度百科. 总之知道它可以求二分图最大权完美匹配就可以了,时间复杂度为O(n^3). 给张图. 二分图有了边权,求最大匹配下的最大权值. 所以该怎么做呢?对啊 ...
- 【二分图最大权完美匹配】【KM算法】【转】
[文章详解出处]https://www.cnblogs.com/wenruo/p/5264235.html KM算法是用来求二分图最大权完美匹配的.[也就算之前的匈牙利算法求二分最大匹配的变种??] ...
- 二分图最大权完美匹配KM算法
KM算法二分图 KM求得二分图与普通二分图的不同之处在于:此二分图的每条边(男生女生)上都附了权值(好感度).然后,求怎样完美匹配使得权值之和最大. 这,不止一般的麻烦啊. 可以通过一个期望值来求. ...
- 【模板】二分图最大权完美匹配(KM算法)/洛谷P6577
题目链接 https://www.luogu.com.cn/problem/P6577 题目大意 给定一个二分图,其左右点的个数各为 \(n\),带权边数为 \(m\),保证存在完美匹配. 求一种完美 ...
随机推荐
- UITableView中cell的圆角(第一个和最后一个)
, , _width, _height)]; ; view.clipsToBounds = YES; _viewDetal = [[UIView alloc]init ...
- ant+jmeter+crontab实现自动化性能测试
准备工作: 1.下载jmeter(我下载的apache-jmeter-2.13.zip) 2.配置jmeter环境变量,即path前添加jmeter的bin路径) 3.下载ant(我使用的apache ...
- 李洪强iOS开发之添加手势
李洪强iOS开发之添加手势 02 - 添加手势
- 李洪强iOS开发之OC[009] -OC无参方法的声明实现和调用
- iOS在线音乐播放SZKAVPlayer(基于AVPlayer的封装)
由于最近闲着没事,想找有关在线音乐播放的demo学习一下,在gitHub跟code4APP上面查找了很多帖子,结果很多在线音乐都是基于AudioStream实现的,我感觉用起来不太方便.后来突然发现, ...
- Java-在线聊天系统-线程
一.概述 1.目标:在上一个版本非线程的聊天系统中,出于要不断监听接收新client和接收client发出的信息,把accept()和DataInputStream.readUTF()分别写在了whi ...
- 【golang】用container/list实现栈(Stack)
go语言中的container有heap.list.ring,没有stack. 其中heap是优先级队列,虽然有Push()/Pop()接口,但是使用heap要实现heap.Interface接口,不 ...
- MainWndProc运行观察
MainWndProc运行观察 把MainWndProc改写成如下代码,便于观察:procedure TWinControl.MainWndProc(var Message: TMessage);be ...
- 拥有更好性能的requesAnimationFrame(Better Performance with requestAnimationFrame)
介绍: 这篇文章讨论的是你可以(也应该)学习通过使用requestAnimationFrame API,而不是使用之前的setInterval/setTimeout方法,来提高动画的性能:如何使用re ...
- O(1)时间内删除指定链表结点
题目 给定单链表头指针和一个结点指针,定义一个函数在O(1)时间内删除该结点. 分析 对于上图实例链表(a)删除指针p有两种方式 思路1:(b)找到前一个指针pre,赋值pre->next = ...