KM算法

代码

//首先init,传进去的参数分别是两边的点的个数,然后调用solve,如果是求
//最小值,改为负数,相当于的求负数的最大值。
struct KM
{
    int W[maxn][maxn],n,m;
    int Lx[maxn],Ly[maxn];
    int To[maxn];
    bool S[maxn],T[maxn];
    void init(int nn,int mm)
    {
        n=nn; m=mm;
        memset(To,-1,sizeof(To));
        for(int i=1;i<=n;i++) //下标要从1开始
        {
            Lx[i]=Ly[i]=0;
            for(int j=1;j<=m;j++) Lx[i]=max(Lx[i],W[i][j]);
        }
    }
    bool Match(int u)
    {
        S[u]=true;
        for(int v=1;v<=m;v++)
            if(Lx[u]+Ly[v]==W[u][v]&&!T[v])
        {
            T[v]=true;
            if(To[v]==-1||Match(To[v]))
            {
                To[v]=u;
                return true;
            }
        }
        return false;
    }
    void Update()
    {
        int a=INF;
        for(int i=1;i<=n;i++)
        {
            if(!S[i]) continue;
            for(int j=1;j<=m;j++)
                if(!T[j]) a=min(a,Lx[i]+Ly[j]-W[i][j]);
        }
        for(int i=1;i<=n;i++) if(S[i]) Lx[i]-=a;
        for(int i=1;i<=m;i++) if(T[i]) Ly[i]+=a;
    }
    int solve()
    {
        for(int i=1;i<=n;i++)
        {
            while(true)
            {
                for(int j=1;j<=m;j++) S[j]=T[j]=0;
                if(Match(i)) break;
                Update();
            }
        }
        int ret=0;
        for(int i=1;i<=m;i++)
            if(To[i]!=-1) ret+=W[To[i]][i];
        return ret;
    }
}km;
View Code

 

posted @ 2016-08-22 11:12  wust_ouyangli  阅读(130)  评论(0编辑  收藏  举报