KM algorithm mark

发布于 2019-11-02  2197 次阅读


KM板子来源:(id:ADream) http://uoj.ac/submission/369757
题目:cf1107F

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define nn 1002
#define LL long long
#define ll long long
#define oo ((LL)1e+18)
#define M(x) memset(x,0,sizeof(x))
#define Mp(x) memset(x,-0x7f,sizeof(x))
using namespace std;

int n;
int A[nn],B[nn],K[nn];

struct KM{
    #define maxn nn
    const ll inf = 1ll << 60;
    ll G[maxn][maxn], hl[maxn], hr[maxn], dt[maxn];
    int fl[maxn], fr[maxn], vl[maxn], vr[maxn], pre[maxn], q[maxn], ql, qr, n;
    void init(int nl, int nr){
        n = max(nl, nr);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j) G[i][j] = 0;
    }
    void add(int u, int v, ll w){
        G[u][v] = max(G[u][v], w);
    }
    int check(int i){
        if(vl[i] = 1, fl[i] != -1) return vr[q[qr++] = fl[i]] = 1;
        while(i != -1) swap(i, fr[fl[i] = pre[i]]);
        return 0;
    }
    void bfs(int s){
        for(int i = 1; i <= n; ++i) vl[i] = vr[i] = 0, dt[i] = inf;
        for(vr[q[ql = 0] = s] = qr = 1;;){
            for(ll d; ql < qr;){
                for(int i = 1, j = q[ql++]; i <= n; ++i){
                    if(!vl[i] && dt[i] >= (d = hl[i] + hr[j] - G[i][j])){
                        if(pre[i] = j, d) dt[i] = d;
                        else if(!check(i)) return;
                    }
                }
            }
            ll d = inf;
            for(int i = 1; i <= n; ++i){
                if(!vl[i] && d > dt[i]) d = dt[i];
            }
            for(int i = 1; i <= n; ++i){
                if(vl[i]) hl[i] += d;
                else dt[i] -= d;
                if(vr[i]) hr[i] -= d;
            }
            for(int i = 1; i <= n; ++i){
                if(!vl[i] && !dt[i] && !check(i)) return;
            }
        }
    }
    ll solve(){
        for(int i = 1; i <= n; ++i) fl[i] = fr[i] = -1, hr[i] = 0;
        for(int i = 1; i <= n; ++i) hl[i] = *max_element(G[i] + 1, G[i] + 1 + n);
        for(int i = 1; i <= n; ++i) bfs(i);
        ll ret = 0;
        for(int i = 1; i <= n; ++i) if(G[i][fl[i]]) ret += G[i][fl[i]]; else fl[i] = 0;
        return ret;
    }
} km;

int main()
{
    freopen("F.in","r",stdin);
    freopen("F.out","w",stdout);

    scanf("%d\n",&n);
    km.init(n,n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d%d\n",A+i,B+i,K+i);
        for(int j=1;j<=n;++j)
        {
            km.add(i,j,max(0LL,1LL*A[i]-1LL*min(K[i],j-1)*B[i]));
        }
    }
    LL ans=km.solve();
    printf("%lld",ans);

    return 0;
}


WRYYYYYYYYY!