• 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("
    ")
    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
    ", ans[c]);
    	}
    } 
    
  • 相关阅读:
    $Noip2011/Luogu1311$ 选择客栈
    $Noip2013/Luogu1970$ 花匠 $dp$+思维
    $CF1063B Labyrinth$ $01$最短路/$01BFS$
    $UVA10559 Blocks $区间$dp$
    $SCOI2009 windy$数 数位$dp$
    $cometoj#4 D $求和 不是$dp$
    Manacher算法总结
    题解 P1537 【弹珠】
    题解 P4609 【[FJOI2016]建筑师】
    字符串专题随笔
  • 原文地址:https://www.cnblogs.com/coldchair/p/13460111.html
Copyright © 2020-2023  润新知