Ural1076(km算法)

题目大意  

给出n*n表格,第a[i,j]表示i到j的权值,现在我们要将每个a[i,j]=sum[j]-a[i,j],

求出当前二分图a[][]最小匹配

最小匹配只需将权值取负后,求二分图最大匹配,使用km算法(即之前blog中代码稍微改了一下)

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int lx[200],ly[200],w[200][200],pre[200];
int n,ans,mi;
bool sx[200],sy[200];
bool path(int p){
    sx[p]=1;
    int i;
    for(i=1;i<=n;i++)
    if (!sy[i]&&lx[p]+ly[i]==w[p][i]){
        sy[i]=1;
        if (pre[i]==0||path(pre[i])){
            pre[i]=p;
            return 1;
        }
    }
    return 0;
}
int main()
{
    int i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++) lx[i]=-10000000;
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++){
        scanf("%d",&w[i][j]);
        w[n+1][j]+=w[i][j];
        }
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++){
        w[i][j]=-(w[n+1][j]-w[i][j]);
        if (w[i][j]>lx[i]) lx[i]=w[i][j];
    }
    for(i=1;i<=n;i++){
        memset(sx,0,sizeof(sx));
        memset(sy,0,sizeof(sy));
        while (!path(i)){
            mi=2000000000;
            for(j=1;j<=n;j++)
                for(k=1;k<=n;k++)
                if (sx[j]&&!sy[k]){
                    if (lx[j]+ly[k]-w[j][k]<mi) mi=lx[j]+ly[k]-w[j][k];
                }
            for(j=1;j<=n;j++) if(sx[j]) lx[j]-=mi;
            for(j=1;j<=n;j++) if(sy[j]) ly[j]+=mi;
            memset(sx,0,sizeof(sx));
            memset(sy,0,sizeof(sy));
        }
    }
    for(i=1;i<=n;i++)
        ans+=-(lx[i]+ly[i]);
    printf("%d",ans);
    return 0;
}


那么多的束缚,我不曾放弃过;那么多的险阻,我不曾倒下过。
原文地址:https://www.cnblogs.com/Mathics/p/3681193.html