KM求每个大小的匹配的最优解 模板
参考cz_xuyixuan的营员交流。
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
int tp;
const int N = 505;
int n, Q;
int a[N][N];
const int inf = 2e9;
ll ans[N];
namespace km {
int nl, nr;
int visx[N], visy[N], chox[N], choy[N], fr[N];
int sla[N], x[N], y[N];
void work() {
fo(i, 1, nl) x[i] = inf;
fo(s, 1, n) {
fo(i, 1, nr) visy[i] = fr[i] = 0, sla[i] = inf;
fo(i, 1, nl) {
if(!chox[i]) {
visx[i] = 1;
fo(j, 1, nr) {
ll v = x[i] + y[j] - a[i][j];
if(v < sla[j]) {
sla[j] = v;
fr[j] = i;
}
}
} else visx[i] = 0;
}
int found = 0;
while(!found) {
int mi = inf;
fo(i, 1, nr) if(!visy[i]) mi = min(mi, sla[i]);
fo(i, 1, nl) if(visx[i]) x[i] -= mi;
fo(i, 1, nr) if(visy[i]) y[i] += mi; else sla[i] -= mi;
fo(i, 1, nr) if(!visy[i] && sla[i] == 0) {
visy[i] = 1;
if(!choy[i]) {
found = 1;
int p = fr[i], q = i;
while(q) {
int nq = chox[p];
chox[p] = q, choy[q] = p;
q = nq, p = fr[q];
}
break;
} else {
int p = choy[i];
visx[p] = 1;
fo(j, 1, nr) {
int v = x[p] + y[j] - a[p][j];
if(v < sla[j]) {
sla[j] = v;
fr[j] = p;
}
}
}
}
}
ans[s] = 0;
fo(i, 1, nl) if(chox[i])
ans[s] += a[i][chox[i]];
}
}
}
int main() {
freopen("allocation.in", "r", stdin);
freopen("allocation.out", "w", stdout);
scanf("%d", &tp);
scanf("%d %d", &n, &Q);
fo(i, 1, n) {
fo(j, 1, n) scanf("%d", &a[i][j]);
}
km :: nl = km :: nr = n;
km :: work();
fo(ii, 1, Q) {
int c; scanf("%d", &c);
c = min(c, n);
pp("%lld.0\n", ans[c]);
}
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址