链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2255

 

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 550
#define INF 0x3f3f3f3f

int n;
int G[N][N], lx[N], ly[N];//x集合的顶标
int visx[N], visy[N], s[N], used[N];//s是为了找d, visx[i]x中的i有没有被增广过

bool Find(int u)//增广路
{
    visx[u] = 1;
    for(int i=1; i<=n; i++)
    {
        if(!visy[i] && lx[u]+ly[i]==G[u][i])
        {
            visy[i]=1;
            if(!used[i] || Find(used[i]))
            {
                used[i] = u;
                return true;
            }
        }
        else
            s[i] = min(s[i], lx[u]+ly[i]-G[u][i]);
    }
    return false;
}

int KM()
{
    memset(used, 0, sizeof(used));
    memset(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], G[i][j]);

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
            s[j] = INF;
        while(1)
        {
            memset(visx, 0, sizeof(visx));
            memset(visy, 0, sizeof(visy));

            if(Find(i))
                break;

            int d = INF;
            for(int j=1; j<=n; j++)
                if(!visy[j])
                    d = min(d, s[j]);

            for(int j=1; j<=n; j++)
            {
                if(visx[j])
                    lx[j] -= d;
                if(visy[j])
                    ly[j] += d;
            }
        }
    }

    int res=0;
    for(int i=1; i<=n; i++)
        res += G[used[i]][i];
    return res;
}

int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        int i, j;
 
        memset(G, 0, sizeof(G));
        for(i=1; i<=n; i++)
        for(j=1; j<=n; j++)
            scanf("%d", &G[i][j]);

        printf("%d\n", KM());
    }
    return 0;
}

 

posted on 2015-08-08 11:49  栀蓝  阅读(164)  评论(0编辑  收藏  举报

levels of contents