KM求每個大小的匹配的最優解 模板
阿新 • • 發佈:2020-08-08
參考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]); } }