HDU 2255 奔小康赚大钱 KM算法的简单解释
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算法的简单解释的更多相关文章
- hdu 2255 奔小康赚大钱--KM算法模板
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...
- hdu 2255奔小康赚大钱 KM算法模板
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=2255 一,KM算法:(借助这个题写一下个人对km的理解与km模板) KM算法主要是用来求解图的最优匹 ...
- HDU - 2255 奔小康赚大钱 KM算法 模板题
HDU - 2255 题意: 分配n所房子给n个家庭,不同家庭对一所房子所需缴纳的钱是不一样的,问你应当怎么分配房子,使得最后收到的钱最多. 思路: KM算法裸题.上模板 #include <i ...
- hdu 2255 奔小康赚大钱 KM算法
看到这么奇葩的题目名我笑了,后来这么一个裸的KM调了2小时我哭了…… 这是个裸的KM算法,也没什么多说的,主要是注意多组数据时,每次都要把各种数组清空啊,赋值啊什么的,反正比较麻烦.至于为什么调了2小 ...
- 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 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊 ...
随机推荐
- OSCache 使用
引入OSCache的jar包 package com.sun.utils; import java.util.Date; import com.opensymphony.oscache.base.Ne ...
- C/C++的静态库与动态库
C/C++编程中相关文件后缀(以Linux系统下为例): .a: 静态库(archive) .c/.cpp: C/C++源程序 .h/.hpp: C/C++源程序的头文件 .i: ...
- 付款前.检查状态.防止重复付款,需要ajax设置为同步,等待ajax返回结果再使用
$("#surePay").on("touchstart",function(){ var apply_id = $('#apply_id').val(); v ...
- Android LayoutInflater解析
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById(). 不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实 ...
- ubuntu 14.04 cagl
libboost-atomic1.-dev libboost-atomic1.-dev libboost-chrono1.-dev libboost-dev libboost-program-opti ...
- delphi 中sql的语法规范
1.引号配对: 这是在Delphi使用SQL语句时容易出错的地方,由于delphi规定在字符串中用两个西文的单引号“''”表示一个“'”,在拼装语句的时候就容易疏忽遗漏. Delphi里有个函数Q ...
- js 有关字符串的函数 以及一些和字符串有关的知识
JS自带函数 concat 将两个或多个字符的文本组合起来,返回一个新的字符串. var a = "hello"; var b = ",world"; var ...
- Gentoo安装详解(三)-- 配置系统
配置系统 系统信息: 文件系统信息: 创建/etc/fstab nano -w /etc/fstab 网络信息: Host name, Domainname, etc nano -w /etc/con ...
- JPA 系列教程11-复合主键-2个@Id
复合主键 指多个主键联合形成一个主键组合 需求产生 比如航线一般是由出发地及目的地确定,如果要确定唯一的航线就可以用出发地和目的地一起来表示 ddl语句 CREATE TABLE `t_airline ...
- mac mysql下载
mysql下载地址:http://dev.mysql.com/downloads/mysql/,不需要账号的 mysql创建数据库,默认字符集是latin1,可以指定字符集. mac删除mysql c ...