hdu 2255奔小康赚大钱 KM算法模板
题目链接:http://acm.hdu.edu.cn/showproblem.php?
pid=2255
一,KM算法:(借助这个题写一下个人对km的理解与km模板)
KM算法主要是用来求解图的最优匹配的。
1。带权二分图: 在二分图中每一条边(x。y)相应一个权值Wi这样的二分图叫带权二分图。
一个匹配的权值就是该匹配中全部边的权值之和。
2,最优匹配:
权值最大的一个完美匹配。叫做最优匹配。
《km算法思想》
对于一个带权全然二分图:G(V。E),对于当中每一条边(x。y)边都相应一个权值W(x,y)。
因为是二分图所以节点集合能够分解成两个集合(X。Y)。X={x1。x2。,,。。xn},Y={y1,y2。,。。yn}。
可行性标签:我们将在全部顶点上定义一个实函数F,且对全部定点满足:F(x)+ F(y)>=W(x,y),
则我们称F为图G的一个可行性标签。
(这里能够理解成F是对顶点加权值F(x))
平庸标签:对于每个图都有存在这样一个标签 l:
称该标签为平庸标签
相等子图:对于每个标签都相应原图的一个子图:G’=(V’,E’) ,当中V’=V。E’属于E,
且E’中全部边满足:F(x) + F(y)=W(x,y) 。该子图称为可行性标签的F的相等子图。
定理:(KM最重要的定理)
对于一个可行性标签L,其相等子图G’,若存在完美匹配M。则该匹配必是原图G的完美匹配。
由于G中与G’中的节点是全然一样的,且对于该匹配的权值为:
所以对于最大的可行性标签L,若它的相等子图G‘含有完美匹配M,则M就是原图的最优匹配。
注意:上面的平庸匹配就是全部匹配中最大的匹配。
匈牙利树:
匈牙利树。事实上是一颗DFS搜索树。
可是在搜索是有条件限制。
(1)。该树必需要从未匹配点開始搜索。即,该树必须以未匹配点为根。
(2)。并且在搜索过程中仅仅能走叫错路。
(3)。叶子节点必须是匹配点
注意:若有叶子节点为未匹配点则从树根到该节点一定有一条增广路。
事实上在匈牙利算法中,若我们从一个未匹配的点。利用DFS找增广路。若到最后我们没找到增广路。
则我们DFS搜索过程的路线就是一颗DFS树且是一颗匈牙利树,且在匈牙利算法中树我们能够永久
性的地把匈牙利树从图中删去,而不影响结果。即:这颗树对树以外的节点的匹配没有影响。
在上图中(2)不是匈牙利树由于有一个叶子节点7,非常明显有一条2到7的增广路。
(3)是一颗匈牙利树。
更新可行性标签:
当我们在当前大的可行性标签l下。无法在L相等子图中找到完美匹配,
这时我们要更新可行性标签,
事实上就是在原来的可行性标签l下降低最小的一个值(key)得到还有一个可行性标签L。
更新方程为:
《KM算法》
如果二分图为:G=(V,E),(X。Y)= V。X={x1。x2。,,。,xn}。Y={y1,y2,,,,yn}。
1。初始化可行性标签L为平庸标签(最大标签)。
2。在可行性标签相等子图G’=(V。E’)中用匈牙利算法(DFS)对X集合中节点一个个进行匹配。
若在匹配过程中,若有X集合中的点没匹配成功。转向(3)
(3)匹配失败这时DFS索搜出的路径必然是一颗匈牙利树。
由匈牙利树性质可知匈牙利树中的节点与边与匈牙利树外部是相互独立的,所以我们改变匈牙利
树种节点的可行新标签就可以。且不会对其他树外有影响,于是我们利用上面标签转化公式改变
匈牙利中节点的可行性标签,然后再转向(2)。
Km 例题:
令:图节点为:V1={x1,x2,x3,x4,x5} 。V2={y1。y2,y3。y4,y5}。边矩阵为:
初始化可行性标签(平庸标签)
L(y1)= L(y2) = L(y3) = L(y4) = L(y5) = 0,
L(x1)=max(3,5,5,4,1)=5 , L(x2)=max(2,2,0,2,2) =2 ,L(x3)=max(2,4,4,1,0) =4
L(x4)=max(0,1,1,0,0) =1 。L(x4)=max(0,1,1,0,0) =1 。
L的相等子图为:
L相等子图的匹配(匹配到x4点失败)
x4搜索出的匈牙利树为:
则 S={x4,x1,x3}。T={y2,y3} 利用可行性标签变换公式为L’:
可得到:key=1;改变:
L’(x1)=4。L’(x2)= 2, L’(x4)=0 ; L’(y2)=1。L’(y3)=1。
然后x4继续匹配:能够匹配完:
这上图L’完美匹配也就是原图最优匹配。
W(M)=12。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
const int Max=310;
const int Inf=(1<<31)-1;
int N;
int graph[Max][Max];//图
int match[Max];//行匹配
int l_x[Max];//x可行性标签
int l_y[Max];//y可行性标签
int usedx[Max];//标记数组
int usedy[Max]; bool Hungary(int x)
{//匈牙利DFS
usedx[x]=true;
for(int i=0;i<N;i++)
{
if(!usedy[i] && l_x[x]+l_y[i]==graph[x][i])
{
usedy[i]=true;
if(match[i]==-1 || Hungary(match[i]))
{
match[i]=x;
return true;
}
}
}
return false;
} void KM()
{
memset(l_x,0,sizeof(l_x));
memset(l_y,0,sizeof(l_y));
for(int i=0; i<N; i++)
{//初始化可信性标签
for(int j=0; j<N; j++)
{
if(l_x[i]<graph[i][j])
l_x[i]=graph[i][j];
}
}
for(int i=0;i<N;i++)
{//匹配V1所以点
while(1)
{
memset(usedx,false,sizeof(usedx));
memset(usedy,false,sizeof(usedy));
if(Hungary(i))
break;//匹配成功就跳出
else
{//匹配失败 匈牙利树节点更新
int tem=Inf;//求最小的 key
for(int j=0;j<N;j++)
{//用到那公式
if(usedx[j])
{
for(int k=0;k<N;k++)
{
if(!usedy[k] && l_x[j]+l_y[k]-graph[j][k]<tem)
tem= l_x[j]+l_y[k]-graph[j][k];
}
}
}
for(int j=0;j<N;j++)
{//更新匈牙利树可行性标签
if(usedx[j])
l_x[j]-=tem;
if(usedy[j])
l_y[j]+=tem;
}
}
}
}
} int main()
{
while(scanf("%d",&N)!=EOF)
{
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
scanf("%d",&graph[i][j]);
memset(match,-1,sizeof(match));
KM();
int total=0;
for(int i=0;i<N;i++)
{
total+=l_x[i];
total+=l_y[i];
}
cout<<total<<endl;
}
return 0;
}
hdu 2255奔小康赚大钱 KM算法模板的更多相关文章
- hdu 2255 奔小康赚大钱--KM算法模板
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...
- HDU - 2255 奔小康赚大钱 KM算法 模板题
HDU - 2255 题意: 分配n所房子给n个家庭,不同家庭对一所房子所需缴纳的钱是不一样的,问你应当怎么分配房子,使得最后收到的钱最多. 思路: KM算法裸题.上模板 #include <i ...
- hdu 2255 奔小康赚大钱 KM算法
看到这么奇葩的题目名我笑了,后来这么一个裸的KM调了2小时我哭了…… 这是个裸的KM算法,也没什么多说的,主要是注意多组数据时,每次都要把各种数组清空啊,赋值啊什么的,反正比较麻烦.至于为什么调了2小 ...
- HDU 2255 奔小康赚大钱 KM算法的简单解释
KM算法一般用来寻找二分图的最优匹配. 步骤: 1.初始化可行标杆 2.对新加入的点用匈牙利算法进行判断 3.若无法加入新编,修改可行标杆 4.重复2.3操作直到找到相等子图的完全匹配. 各步骤简述: ...
- HDU 2255 奔小康赚大钱 KM算法题解
KM算法求的是完备匹配下的最大权匹配,是Hungary算法的进一步,由于Hungary算法是最大匹配的算法,不带权. 经典算法,想不出来的了,要參考别人的.然后消化吸收吧. 由于真的非常复杂的算法. ...
- hdu 2255 奔小康赚大钱 (KM)
奔小康赚大钱Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- HDU 2255 奔小康赚大钱 KM裸题
#include <stdio.h> #include <string.h> #define M 310 #define inf 0x3f3f3f3f int n,nx,ny; ...
- 二分图最大权匹配问题&&KM算法讲解 && HDU 2255 奔小康赚大钱
作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...
- HDU 2255 奔小康赚大钱(带权二分图最大匹配)
HDU 2255 奔小康赚大钱(带权二分图最大匹配) Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊 ...
随机推荐
- 盒子模型,top和margin-top
1. 标准盒子模型: width只是内容的宽度. 元素的总宽度=width + padding*2 +border*2 +margin*2. IE盒子模型: width=内容的宽度 + padding ...
- 多路开关模式的switch语句
在实例10中,将break语句去掉之后,会将符合检验条件后的所有语句都输出.利用这个特点,可以设计多路开关模式的switch语句,例如:在平年一年12个月,1.3.5.7.8.10.12月是31天,4 ...
- python行与缩进
#python行与缩进 1.了解逻辑行与物理行 2.行中分号使用规则 3.行链接 4.什么是缩进 5.如何缩进 6.注释 1.python中逻辑行主要是指一段代码,在意义上它的行数,而物理行,指的是我 ...
- iOS 声明属性关键字讲解
atomic: 原子操作(原子性是指事务的一个完整操作,操作成功就提交,反之就回滚. 原子操作就是指具有原子性的操作)在objective-c 属性设置里面 默认的就是atomic ,意思就是 set ...
- Sqoop hive 和mysql 交互 完整案例
本文完成:在hive里建管理表:注入部分数据:利用sqoop导入mysql中 期间:解决中文乱码问题 飞行报告故障表 建表命令 查看表 人工灌入少量数据 Windows系统向Linux系统数据传输 ...
- 如何创建C# Closure?
JavaScript中一个重要的概念就是闭包,闭包在JavaScript中有大量的应用,但是你知道么?C#也可以创建Closure.下面就介绍一下如何在C#中创建神奇的闭包. 在这之前,我们必须先知道 ...
- 如何实现ADSL宽带用户开机自动拨号与定时拨号
在宽带拨号网络的环境下,要通过手动拨号认证才能上网.下面给大家介绍怎么设置开机自动拨号上网以及定时拨号上网. 这也是为一个叫CHY的2B准备的技术套餐,不需要用到网上说的自动拨号软件,只要在主机上设置 ...
- C#基础知识面试经典[整理]
个人网站:http://www.51pansou.com .net视频下载:.net视频教程 .net源码下载:.net源码 当初学 C# 时是找个人大概问了一下数据类型和分支语句就开始做项目了.这两 ...
- MySql学习笔记(四) —— 数据的分组
前面介绍的聚集函数只是用来计算行数,平均数,最大值,最小值而不用检索所有数据.通过count()函数,我们可以计算生产商1003提供的产品数目,但如果我要查询所有生产商提供的商品数,这就需要进行分组查 ...
- 一天搞定jQuery(三)——使用jQuery完成复选框的全选和全不选
还记得之前我使用JavaScript来实现复选框的全选和全不选效果吗?如果读者初次翻阅本文,可记得看看教你一天玩转JavaScript(七)——使用JavaScript完成复选框的全选和全不选的效果! ...