KM算法一般用来寻找二分图的最优匹配。

步骤:

1.初始化可行标杆

2.对新加入的点用匈牙利算法进行判断

3.若无法加入新编,修改可行标杆

4.重复2.3操作直到找到相等子图的完全匹配。

各步骤简述:

1.根据二分图建立2个可行标杆;

lx为x的可行标杆,初始化lx[i]为与i点相连的最大边

ly为y的可行标杆,初始化为0.

可行性的判断条件应为lx[x]+ly[y] >= Map[x][y]。

2.对于新加入的点用匈牙利算法经行判断,确定改点能否加入旧子图中,形成新子图。

对于该加入的点有两种可能:

2.1.找到某个y点,该y点为被连接,则与该点相连,并符合条件

2.2找到某个y点,该y点已经被某x1点所连接,则对x1点经行深搜,若x1可以找到新的连接点,则修改x1的连接路径,并使x点与y点相连。

3.如果发现无法再向已有的相等子图中加入边,则证明不再有lx[x]+ly[y]==Map[x][y]成立,那么我们对x和y的可行标杆经行修改。

当找不到增广路径时,对于搜索过的路径上的XY点,设该路径上的X顶点集为S,Y顶点集为T,对所有在S中的点xi及不在T中的点yj,计算d=min{(L(xi)+L(yj)-weight(xiyj))},从S集中的X标杆中减去d,并将其加入到T集中的Y的标杆中,由于S集中的X标杆减少了,而不在T中的Y标杆不变,相当于这两个集合中的lx(x)+ly(y)变小了,也就是,lx[x]+ly[y]将变小,便有可能有lx[x]+ly[y]==Map[x][y]成立,即可能会加入新的边。

4.重复2.3过程,知道找到完备相等子图为止。

时间复杂度:优化后大概为O(n^3);

代码:

#include<cstdio>
#include<stdio.h>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define INF 0x3f3f3f3f
#define MAX 1005
#define mod 1000000007 using namespace std; int visx[MAX],visy[MAX],lx[MAX],ly[MAX],linker[MAX],slack[MAX],Map[MAX][MAX],n; bool DFS(int x)
{
visx[x]=;
for(int y=;y<=n;y++)
{
if(visy[y])
continue;
int tmp=lx[x]+ly[y]-Map[x][y];
if(tmp==)
{
visy[y]=;
if(linker[y]==- || DFS(linker[y]))
{
linker[y]=x;
return true;
}
}
else
{
slack[y]=min(slack[y],tmp);
}
}
return false;
} int KM()
{
int i,j;
memset(ly,,sizeof(ly));//初始化可行标杆ly
memset(linker,-,sizeof(linker));
for(i=; i<=n; i++)//初始化可行标杆lx
{
lx[i]=-INF;
for(j=; j<=n; j++)
lx[i]=max(lx[i],Map[i][j]);
} for(int x=; x<=n; x++)
{
for(i=; i<=n; i++)
slack[i]=INF;
while()
{
memset(visx,,sizeof(visx));
memset(visy,,sizeof(visy));
if(DFS(x))//若可加入直接跳出
break;
int d=INF;
for(i=; i<=n; i++)
{
if(!visy[i])
d=min(slack[i],d);//否则根据贪心的思想,找到最小的可行标杆修改值
}
for(i=; i<=n; i++)//修改lx标杆
{
if(visx[i])
lx[i]-=d;
}
for(i=; i<=n; i++)//修改ly标杆
{
if(visy[i])
ly[i]+=d;
else
slack[i]-=d;//slack由lx[x]+ly[y]-Map[x][y]而来;ly中未标记过的值不变,lx中已标记过的值减少,则slack应减少
}
}
}
int ans=;
for(i=;i<=n;i++)
{
ans+=Map[linker[i]][i];
}
return ans;
} int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=; i<=n; i++)
{
for(int j=; j<=n; j++)
scanf("%d",&Map[i][j]);
} int ans=KM();
printf("%d\n",ans);
}
return ;
}

HDU 2255 奔小康赚大钱 KM算法的简单解释的更多相关文章

  1. hdu 2255 奔小康赚大钱--KM算法模板

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...

  2. hdu 2255奔小康赚大钱 KM算法模板

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=2255 一,KM算法:(借助这个题写一下个人对km的理解与km模板) KM算法主要是用来求解图的最优匹 ...

  3. HDU - 2255 奔小康赚大钱 KM算法 模板题

    HDU - 2255 题意: 分配n所房子给n个家庭,不同家庭对一所房子所需缴纳的钱是不一样的,问你应当怎么分配房子,使得最后收到的钱最多. 思路: KM算法裸题.上模板 #include <i ...

  4. hdu 2255 奔小康赚大钱 KM算法

    看到这么奇葩的题目名我笑了,后来这么一个裸的KM调了2小时我哭了…… 这是个裸的KM算法,也没什么多说的,主要是注意多组数据时,每次都要把各种数组清空啊,赋值啊什么的,反正比较麻烦.至于为什么调了2小 ...

  5. HDU 2255 奔小康赚大钱 KM算法题解

    KM算法求的是完备匹配下的最大权匹配,是Hungary算法的进一步,由于Hungary算法是最大匹配的算法,不带权. 经典算法,想不出来的了,要參考别人的.然后消化吸收吧. 由于真的非常复杂的算法. ...

  6. hdu 2255 奔小康赚大钱 (KM)

    奔小康赚大钱Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  7. HDU 2255 奔小康赚大钱 KM裸题

    #include <stdio.h> #include <string.h> #define M 310 #define inf 0x3f3f3f3f int n,nx,ny; ...

  8. 二分图最大权匹配问题&&KM算法讲解 && HDU 2255 奔小康赚大钱

    作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...

  9. HDU 2255 奔小康赚大钱(带权二分图最大匹配)

    HDU 2255 奔小康赚大钱(带权二分图最大匹配) Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊 ...

随机推荐

  1. html5 article标签举例

    <article> 是html5中引入的新标签可以实现正向反向列表排序功能 使用以前的html4进行列表排序,可以使用下列形式 <h1>Top Three Teams</ ...

  2. asp.net正则表达式去除a标签

    if (drr["allow_a"].ToString() == "False") { cont = dr["news_Content"]. ...

  3. Android 中执行定时任务 Timer + TimerTask

    1. new Timer().schedule(new TimerTask() { @Override public void run() { //任务代码 } }, 0, 5000);

  4. storm配置

    配置 Storm 有大量配置项用于调整 nimbus.supervisors 和拓扑的行为.有些配置项是系统级的配置项,在拓扑中不能修改,另外一些配置项则是可以在拓扑中修改的. 每一个配置项都在 St ...

  5. js广告图片轮播

    <div class="box"> <div class="box1"></div> <div class=" ...

  6. vc中主线程等待子线程退出的方法

    VC线程同步,在子线程中等待另一子线程结束,通过WaitForSingleObject可以实现,但是如果在主线程中等待子线程结束,这个函数是无法完成要求的,因为它会造成主线程挂起,导致程序死掉.我们可 ...

  7. UISwitch 开关控件

    UISwitch iOS中的开关控件,只有两种状态,打开或关闭. aSwitch.tintColor = [UIColor redColor]; //关闭状态下的渲染颜色 aSwitch.onTint ...

  8. javascript动画效果之多物体缓冲运动

    这个是通过一个for循环控制的三个li标签,被鼠标触发则会有一个宽度增加和减少的事件 html和css同样写在一起方便察看,这里就是简单的布局,重点在js <!DOCTYPE html> ...

  9. c# 获取命名空间 类名 方法名

    c# 获取命名空间 类名 方法名 转[http://blog.sina.com.cn/s/blog_3fc2dcc1010189th.html]   分类: Winform public static ...

  10. javascript performence

    1.将脚本放在底部 javascript是阻塞式的加载,如果先加载脚本,后面的dom都没有办法进行渲染,页面会是一片空白: 采用无阻塞下载javascript a.使用<script>标签 ...