hud2255 km template, weighted bipartite graph matching

km can solve some card cost flow problems
Time complexity n3

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstdlib>
#define inf 0x3f3f3f3f

using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int maxn = 350;
void acc_ios()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
}
int mp[maxn][maxn];
int slack[maxn];
int nx, ny;
int lx[maxn], ly[maxn];
int visx[maxn], visy[maxn];
int link[maxn];

bool dfs(int x)
{
    
    
    visx[x] = 1;
    for(int i = 1; i <= ny; i++)
    {
    
    
        if(visy[i]) continue;
        int tmp = lx[x] + ly[i] - mp[x][i];
        if(tmp == 0)
        {
    
    
            visy[i] = 1;
            if(link[i] == -1 || dfs(link[i]))
            {
    
    
                link[i] = x;
                return true;
            }
        }
        else if(slack[i] > tmp)
        {
    
    
            slack[i] = tmp;
        }
    }
    return false;
}

int KM()
{
    
    
    memset(link, -1, sizeof(link));
    memset(ly, 0, sizeof(ly));
   // memset(lx, -0x3f, sizeof(lx));
    for(int i = 1; i <= nx; i++)
    {
    
    
        lx[i] = -inf;
        for(int j = 1; j <= ny; j++)
        {
    
    
            lx[i] = max(mp[i][j], lx[i]);
        }
    }
    for(int i = 1; i <= nx; i++)
    {
    
    
        for(int j = 1; j <= ny; j++)
            slack[j] = inf;
        while(1)
        {
    
    
            memset(visx, 0, sizeof(visx));
            memset(visy, 0, sizeof(visy));
            if(dfs(i)) break;
            int d = inf;
            for(int j = 1; j <= ny; j++)
                if(!visy[j] && d > slack[j])
                d = slack[j];
            for(int j = 1; j <= nx; j++)
                if(visx[j])
                lx[j] -= d;
            for(int j = 1; j <= ny; j++)
            {
    
    
                if(visy[j]) ly[j] += d;
                else slack[j] -= d;
            }
        }
    }
    int ans = 0;
    for(int i = 1; i <= ny; i++)
    {
    
    
        if(link[i] > -1)
            ans += mp[link[i]][i];
    }
    return ans;
}

int main()
{
    
    
    acc_ios();
    int n;
    while(cin>>n)
    {
    
    
        nx = ny = n;
        for(int i = 1; i <= n; i++)
        {
    
    
            for(int j = 1; j <= n; j++)
            {
    
    
                cin>>mp[i][j];
            }
        }
        cout<<KM()<<endl;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43891021/article/details/104429943