首页 > 代码库 > hdu 2255 二分图带权匹配 模板题

hdu 2255 二分图带权匹配 模板题

模板+注解在 http://blog.csdn.net/u011026968/article/details/38276945


hdu 2255 代码:

//KM×î´ó×îСƥÅä
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

#define INF 0x0fffffff
const int MAXN = 300+10;
int n,match[MAXN];
bool sx[MAXN],sy[MAXN];
int lx[MAXN],ly[MAXN],mat[MAXN][MAXN];

bool path(int u)
{
    sx[u]=true;
    for(int v=0;v<n;v++)
        if(!sy[v] && lx[u]+ly[v]==mat[u][v])
        {
            sy[v]=true;
            if(match[v] == -1 || path(match[v]))
            {
                match[v]=u;
                return true;
            }
        }
    return false;
}

int KM()
{
    for(int i=0;i<n;i++)
    {
        lx[i]=-INF;
        ly[i]=0;
        for(int j=0;j<n;j++)
            lx[i]=max(lx[i], mat[i][j]);
    }

    memset(match, -1, sizeof(match));
    for(int u=0;u<n;u++)
        while(1)
        {
            memset(sx,0,sizeof(sx));
            memset(sy,0,sizeof(sy));
            if(path(u))break;
            int dmin=INF;
            for(int i=0;i<n;i++)
                if(sx[i])
                    for(int j=0;j<n;j++)
                        if(!sy[j])
                            dmin=min(lx[i]+ly[j]-mat[i][j],dmin);

            for(int i=0;i<n;i++)
            {
                if(sx[i])
                    lx[i]-=dmin;
                if(sy[i])
                    ly[i]+=dmin;
            }
        }
    int sum=0;
    for(int j=0;j<n;j++)
        sum+=mat[match[j]][j];
        //if(mat[match[j]][j])
    return sum;
}

int main()
{
    //freopen("hdu2255.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        ////init()??
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                mat[i][j]=INF;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                scanf("%d",&mat[i][j]);
            }
        printf("%d\n",KM());
    }
    return 0;
}