HDU2255 二分图最佳匹配(KM 算法)

2017年7月29日

很直白的一道二分图最佳匹配题.就拿来练练模板就好.

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 305;
int w[N][N];
int slack[N];
int visx[N], visy[N];
int lx[N], ly[N];
int link[N];
int n;
bool match(int u)
{
    visx[u] = 1;
    for (int y = 0; y < n; y++) {
        if (visy[y])
            continue;
        int t = lx[u] + ly[y] - w[u][y];
        if (!t) {
            visy[y] = 1;
            if (!~link[y] || match(link[y])) {
                link[y] = u;
                return true;
            }
        } else {
            slack[y] = min(slack[y], t);
        }
    }
    return false;
}
void km()
{
    memset(link, -1, sizeof(link));
    memset(ly, 0, sizeof(ly));
    for (int i = 0; i < n; i++) {
        lx[i] = 0;
        for (int j = 0; j < n; j++) {
            lx[i] = max(lx[i], w[i][j]);
        }
    }
    for (int x = 0; x < n; x++) {
        memset(slack, inf, sizeof(slack));
        for (;;) {
            memset(visx, 0, sizeof(visx));
            memset(visy, 0, sizeof(visy));
            if (match(x)) {
                break;
            }
            int d = inf;
            for (int i = 0; i < n; i++) {
                if (!visy[i])
                    d = min(d, slack[i]);
            }
            for (int i = 0; i < n; i++) {
                if (visx[i])
                    lx[i] -= d;
                if (visy[i])
                    ly[i] += d;
                else
                    slack[i] -= d;
            }
        }
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans += w[link[i]][i];
    }
    printf("%d\n", ans);
}
int main()
{
    while (~scanf("%d", &n)) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int x;
                scanf("%d", &x);
                w[i][j] = x;
            }
        }
        km();
    }
    return 0;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注