Golden Tiger Claw UVA

这题使我对km多了一些看法

写给自己看。。

km结束后bx[i] + by[j] == w[i][j], 所以所有bx与by的和即为w的和

而且记住bx[i] + by[j] >= w[i][j] 这个式子 那么bx与by的最小值 即为km结束后的值

#include <iostream>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 550, INF = 0x7fffffff;
int usedx[maxn], usedy[maxn], w[maxn][maxn], bx[maxn], by[maxn], cx[maxn], cy[maxn];
int nx, ny, n, minn, min_value;

bool dfs(int u)
{
    usedx[u] = 1;
    for(int i=1; i<=ny; i++)
    {
        if(usedy[i] == -1)
        {
            int t = bx[u] + by[i] - w[u][i];
            if(t == 0)
            {
                usedy[i] = 1;
                if(cy[i] == -1 || dfs(cy[i]))
                {
                    cy[i] = u;
                    cx[u] = i;
                    return 1;
                }
            }
            else if(t > 0)
                minn = min(minn, t);
        }
    }
    return 0;
}

int km()
{
    mem(cx, -1);
    mem(cy, -1);
    mem(bx, -1);
    mem(by, 0);
    for(int i=1; i<=nx; i++)
        for(int j=1; j<=ny; j++)
            bx[i] = max(bx[i], w[i][j]);
    for(int i=1; i<=nx; i++)
    {
        while(1)
        {
            minn = INF;
            mem(usedx, -1);
            mem(usedy, -1);
            if(dfs(i)) break;
            for(int j=1; j<=nx; j++)
                if(usedx[j] != -1) bx[j] -= minn;
            for(int j=1; j<=ny; j++)
                if(usedy[j] != -1) by[j] += minn;
        }
    }
    min_value = 0;
    for(int i=1; i<=n; i++)
        if(cx[i] != -1)
            min_value += w[i][cx[i]];

    return min_value;

}

int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&w[i][j]);
        nx = ny = n;
        int ans = km();
    for(int i=1; i<=nx; i++)
    {
        if(i != 1) printf(" ");
        printf("%d", bx[i]);
    }
    printf("
");
    for(int i=1; i<=ny; i++)
    {
        if(i != 1) printf(" ");
        printf("%d", by[i]);
    }
    printf("
");
    cout<< ans <<endl;

    }
    return 0;
}
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
原文地址:https://www.cnblogs.com/WTSRUVF/p/9427996.html