KM算法小结
2017-03-31 22:26
99 查看
正规的算法解释真看不懂。。。。
果然二分图这东西还是得和泡妞有关才好理解。。。 _ (:зゝ∠) _
推荐http://www.cnblogs.com/wenruo/p/5264235.html
我惊讶的发现,空说点实在是不好理解(我智商低←_←),所以,下面把问题改成最令人感兴趣的泡妞问题。。。。
一个点集为男生,一个点集为女生,每一个女生对每一个男生有一个好感度(即边权),问如何配对使得最终好感度的和最大。
ex[i][j]表示第i个妹子对第j个男生的好感度。
接下来的问题就是最大匹配值。
每个妹子都期望有个好归宿,所以她们期望能够和自己好感度最高的男生牵手。
对此,我们引入数组exg[i]表示第i个妹子的期望,初始时exg[i]=max(ex[i][j])(即妹子对所有男生中,好感度最高的男生)。
由于现在社会状况为男女比例严重失调,所以男生已经不在乎妹子颜值了,只希望能有一个妹子就好,所以exb[i]表示第i个男生的期望,初始为exb[i]=0;
女2与男3匹配,然而男3已经匹配过了,不能匹配,其他男生又不符合要求,这一轮匹配宣告失败。
女生中有争执,只好降低自己的期望,女1要想可以匹配其他男生,至少要降低1点期望,女2也同理,所以她们的期望-1,即exg[1]-1,exg[2]-1.
而男3由于得到了妹子的关注,终生大事已经要着落了,自然就开始关注其妹子的颜值了,他的期望就上升1点,即exb[3]+1。
可以发现
1.只有参与匹配的男女才会进行调整。
2.男生上升的期望与女生下降的期望的值是相同的。
然后重复匹配,失败再进行调整,直到成功。
时间复杂度为O(n4)。
如果朴素的寻找最小d,是要n2级别的。
对此,我们可以设一个差距数组les[i],表示第i个男生最少要降低多少期望才能达到和一个妹子匹配的要求。一开始les[i]=∞
当我们匹配一个妹子和男生时,val=exg[i]+exb[j]-ex[i][j],当val=0时说明可以匹配,若val不为0(即val>0),说明男生还差val点期望才能获得这个女生的关注,所以les[j]=min(val,les[j])。
而d就是les中最小的。此时对于没有匹配到的男生,他们离妹子的期待又进了一步,这些男生的les[j]+=d。
时间为O(n)
最终整个算法的复杂度为O(n3)
题目即为上
果然二分图这东西还是得和泡妞有关才好理解。。。 _ (:зゝ∠) _
推荐http://www.cnblogs.com/wenruo/p/5264235.html
正题
KM算法是用于解决带权二分图的完美匹配的最大匹配值。(你不懂完美匹配,恭喜恭喜),是基于匈牙利算法的。我惊讶的发现,空说点实在是不好理解(我智商低←_←),所以,下面把问题改成最令人感兴趣的泡妞问题。。。。
一个点集为男生,一个点集为女生,每一个女生对每一个男生有一个好感度(即边权),问如何配对使得最终好感度的和最大。
ex[i][j]表示第i个妹子对第j个男生的好感度。
思路
首先这东西为完美匹配,我们先把女生对男生没有好感度的(真可怜)视为好感度为0,那么匹配后自然就是一个完美匹配了!接下来的问题就是最大匹配值。
每个妹子都期望有个好归宿,所以她们期望能够和自己好感度最高的男生牵手。
对此,我们引入数组exg[i]表示第i个妹子的期望,初始时exg[i]=max(ex[i][j])(即妹子对所有男生中,好感度最高的男生)。
由于现在社会状况为男女比例严重失调,所以男生已经不在乎妹子颜值了,只希望能有一个妹子就好,所以exb[i]表示第i个男生的期望,初始为exb[i]=0;
匹配前规定
开始匹配时,每一轮匹配中,每一个男生与女生只能尝试匹配一次!要求为ex[i][j]=exg[i]+exb[j](即双方都要满意对方)匹配中
第一轮中,女1与男3匹配,成功。女2与男3匹配,然而男3已经匹配过了,不能匹配,其他男生又不符合要求,这一轮匹配宣告失败。
匹配后
匹配失败后,参与匹配的有女1,女2,男3。女生中有争执,只好降低自己的期望,女1要想可以匹配其他男生,至少要降低1点期望,女2也同理,所以她们的期望-1,即exg[1]-1,exg[2]-1.
而男3由于得到了妹子的关注,终生大事已经要着落了,自然就开始关注其妹子的颜值了,他的期望就上升1点,即exb[3]+1。
可以发现
1.只有参与匹配的男女才会进行调整。
2.男生上升的期望与女生下降的期望的值是相同的。
然后重复匹配,失败再进行调整,直到成功。
时间复杂度为O(n4)。
优化
设男女生调整的期望值为d如果朴素的寻找最小d,是要n2级别的。
对此,我们可以设一个差距数组les[i],表示第i个男生最少要降低多少期望才能达到和一个妹子匹配的要求。一开始les[i]=∞
当我们匹配一个妹子和男生时,val=exg[i]+exb[j]-ex[i][j],当val=0时说明可以匹配,若val不为0(即val>0),说明男生还差val点期望才能获得这个女生的关注,所以les[j]=min(val,les[j])。
而d就是les中最小的。此时对于没有匹配到的男生,他们离妹子的期待又进了一步,这些男生的les[j]+=d。
时间为O(n)
最终整个算法的复杂度为O(n3)
题目
hdu2255题目即为上
代码
#include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<cmath> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=305; int ex[maxn][maxn],exb[maxn],exg[maxn],les[maxn],n,ans,mat[maxn]; bool b[maxn],g[maxn]; bool dfs(int girl) { g[girl]=true; fo(boy,1,n){ if (b[boy]) continue; int val=exg[girl]+exb[boy]-ex[girl][boy]; if (!val){ b[boy]=true; if (mat[boy]==-1||dfs(mat[boy])){ mat[boy]=girl; return true; } } else les[boy]=min(les[boy],val); } return false; } void KM() { fo(i,1,n) exb[i]=0,mat[i]=-1; fo(i,1,n){ exg[i]=ex[i][1]; fo(j,2,n) exg[i]=max(exg[i],ex[i][j]); } fo(i,1,n){ memset(les,127,sizeof(les)); while (1){ fo(j,1,n) b[j]=g[j]=false; if (dfs(i)) break; int d=1e9; fo(j,1,n) if (!b[j]) d=min(d,les[j]); fo(j,1,n){ if (g[j]) exg[j]-=d; if (b[j]) exb[j]+=d; else les[j]-=d; } } } fo(i,1,n) ans+=ex[mat[i]][i]; } int main() { //freopen("T.in","r",stdin); while (scanf("%d",&n)!=EOF){ fo(i,1,n) fo(j,1,n) scanf("%d",&ex[i][j]); ans=0; KM(); printf("%d\n",ans); } }
相关文章推荐
- 【KM算法小结】
- 算法小结——KM算法
- 转,typedef用法小结
- 异常控制try,catch用法小结
- MSSQL安全设置的具体步骤和方法小结
- php编码规范个人小结
- CentOS 6.4升级内核小结
- latex 常用小结
- Android学习之 WebView使用小结
- Vim进行文件目录操作小结
- HDU 2255(KM算法)
- ASP网站生成静态html页面技术小结
- MySQL Query Cache 小结
- 脚本编程小结
- PHP的基本常识小结
- Linux设置环境变量小结:设置永久变量&临时变量 全局变量&局部变量
- jQuery中 attr() 方法使用小结
- 书籍切割之书脊边界直线检测算法小结(bookSpines Segmentation)
- Android 软键盘弹出隐藏挤压界面等各种问题小结
- Zookeeper运维小结--CancelledKeyException