二分图带权匹配

Posted kgxw0430

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图带权匹配相关的知识,希望对你有一定的参考价值。

  带权匹配是指在最大匹配的基础上,使匹配边的边权和最大。一般有两种写法,一个是KM算法(只针对可以完备匹配的二分图),一个是费用流。

  KM算法在稠密图上比费用流更优秀一些,不过应用范围太小,所以还是鼓励大家用费用流。当然啦,作为一种算法KM也是我们需要了解的(况且我不会网络流??)。

  KM算法有个流程:

  1、存图

  2、用贪心算法初始化标杆

  3、运用匈牙利算法找到完备匹配

  4、如果找不到完备匹配,通过修改标杆增加一些边

  5、重复做3和4两个步骤,直到找到完备匹配。

  其他的话,我表述的也不是很好,理解有限抱歉。有一篇很好的博客,推荐一下:http://www.cnblogs.com/Lanly/p/6291214.html

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,ans,delta,w[N][N],match[N],la[N],lb[N],va[N],vb[N];
bool dfs(int x){
    va[x]=1;
    for(int y=1;y<=n;++y){
        if(!vb[y]){
            if(va[x]+vb[y]-w[x][y]==0){
                vb[y]=1;
                if(!match[y]||dfs(match[y])){
                    match[y]=x;
                    return true;
                }
            }else delta=min(delta,la[x]+lb[y]-w[x][y]);
        }
    }
    return false;
}
int KM(){
    for(int i=1;i<=n;++i){
        la[i]=-(1<<30);
        lb[i]=0;
        for(int j=1;j<=n;++j) la[i]=max(la[i],w[i][j]);
    }
    for(int i=1;i<=n;++i){
        while(true){
            memset(va,0,sizeof(va));
            memset(vb,0,sizeof(vb));
            delta=1<<30;
            if(dfs(i)) break;
            for(int j=1;j<=n;++j){
                if(va[j]) la[j]-=delta;
                if(vb[j]) lb[j]-=delta;
            }
        }
    }
    ans=0;
    for(int i=1;i<=n;++i) ans+=w[match[i]][i];
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    for(int j=1;j<=n;++j) scanf("%d",&w[i][j]);
    printf("%d
",KM());
    return 0;
}

 

以上是关于二分图带权匹配的主要内容,如果未能解决你的问题,请参考以下文章

KM——二分图带权最大匹配

Ants 二分图带权最小匹配

hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)

hdu 1829 &amp;poj 2492 A Bug&#39;s Life(推断二分图带权并查集)

网络流常见建图套路总结(重制版)

最大权二分匹配