匈牙利算的是无权边二分图,而KM算法算的是有权边二分图

参考博客:https://blog.csdn.net/chenshibo17/article/details/79933191

 

模板代码:

#include<bits\stdc++.h>
using namespace std;

const int maxn=300+10;
const int inf=1e9;

int wx[maxn], wy[maxn];        //每个点的顶标值
int cx[maxn],cy[maxn];      //每个点所匹配的值
int visx[maxn],visy[maxn];  //每个点是否加入增广路
int cntx,cnty;               
int Map[maxn][maxn];
int minz;
int n,k;

bool dfs(int u)
{
    visx[u]=1;
    for(int v=1;v<=cnty;v++)
    {
        if(!visy[v]&&Map[u][v]!=inf)
        {
            int t=wx[u]+wy[v]-Map[u][v];
            if(t==0)
            {
                visy[v]=1;
                if(cy[v]==-1||dfs(cy[v]))
                {
                    cx[u]=v;
                    cy[v]=u;
                    return 1;
                }
            }
            else if(t>0)
            {
                minz=min(minz,t);
            }
        }
    }
    return false;
}


int KM()
{
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    memset(wx,0,sizeof(wx));
    memset(wy,0,sizeof(wy));
    for(int i=1;i<=cntx;i++)
    {
        for(int j=1;j<=cnty;j++)
        {
            if(Map[i][j]==inf) continue;
            wx[i]=max(wx[i],Map[i][j]);
        }
    }
    for(int i=1;i<=cntx;i++)
    {
        while(1)
        {
            minz=inf;
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(dfs(i))break;
            
            for(int j=1;j<=cntx;j++)
            {
                if(visx[j])
                {
                    wx[j]-=minz;
                }
            }
            for(int j=1;j<=cnty;j++)
            {
                if(visy[i])
                {
                    wy[j]-=minz;
                }
            }
        }
    }
    
    int ans=0;
    for(int i=1;i<=cntx;i++)
    {
        if(cx[i]!=-1)
        {
            ans+=Map[i][cx[i]];
        }
    }
    return ans;
}

int main()
{
    while(~scanf("%d",&n))
    {
        memset(Map,-1,sizeof(Map));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&Map[i][j]);
            }
        }
        cntx=cnty=n;
        printf("%d\n",KM());
    }
}