Lightoj1011【KM算法】

题意:

问男孩女孩最大的可能值?其实就是一个二分图的最大权值匹配问题;模板题吧。。

#include<cstdio>
#include<math.h>
#include<queue>
#include<map>
#include<string>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL mod=1e9+7;

const int N=20;
int ma[N][N];
int lx[N],ly[N],match[N];
bool vx[N],vy[N];
int n,d;

bool Findpath(int u)
{
    vx[u]=1;
    for(int i=1;i<=n;i++)
    {
        if(vy[i]) continue;
        int temp=lx[u]+ly[i]-ma[u][i];
        if(temp==0)
        {
            vy[i]=1;
            if(match[i]==-1||Findpath(match[i]))
            {
                match[i]=u;
                return true;
            }
        }
        else if(d>temp)
            d=temp;
    }
    return false;
}

int KM()
{
    memset(match,-1,sizeof(match));
    memchr(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            lx[i]=max(lx[i],ma[i][j]);
    for(int i=1;i<=n;i++)
    {
        while(1)
        {
            memset(vx,0,sizeof(vx));
            memset(vy,0,sizeof(vy));
            d=INF;
            if(Findpath(i))
                break;
            for(int j=1;j<=n;j++)
            {
                if(vx[j]) lx[j]-=d;
                if(vy[j]) ly[j]+=d;
            }
        }
    }
    int res=0;
    for(int i=1;i<=n;i++)
        res+=ma[match[i]][i];
    return res;
}

int main()
{
    int cas=1,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&ma[i][j]);
            }
        printf("Case %d: ",cas++);
        printf("%d
",KM());
    }
    return 0;
}


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6216786.html