2019 上海邀請賽 I Matrix Game(ZKW模板)

zkw費用流,可以在殘餘網絡上跑。 

注意這裏的 maxflow 和 mincost 沒有在 MFMC 中初始化

還有這裏 反向邊的存儲 通過 op 記錄,不可以通過  ^ 操作實現。

#include <bits/stdc++.h>
using namespace std;
typedef int lint;
const int maxn = 25;
const int inf = 0x3f3f3f3f;
vector<int> e1,e2;
int S,T;
namespace MFMC{
    const int N = 505;
    const int M = 100005;
    const lint inf = 0x3f3f3f3f;
    struct edge {
        int from,to,c,op,next;
        lint w;
    } e[M];
    int vis[N],last[N],tot;
    lint dis[N];
    int s,t;
    void add(int u,int v,int c,lint w) {
        e[++tot].from=u;
        e[tot].to=v;
        e[tot].c=c;
        e[tot].w=w;
        e[tot].op=tot+1;
        e[tot].next=last[u];
        last[u]=tot;
        if( u == S ){
            e1.push_back( tot );
        }
        if( v == T ){
            e2.push_back( tot );
        }
        e[++tot].from=v;
        e[tot].to=u;
        e[tot].c=0;
        e[tot].w=-w;
        e[tot].op=tot-1;
        e[tot].next=last[v];
        last[v]=tot;
        if( u == S ){
            e1.push_back( tot );
        }
        if( v == T ){
            e2.push_back( tot );
        }
    }
    void init( int n ) {
        tot = 0;
        memset( vis,0,sizeof(lint)*(n+1) );
        memset( dis,0,sizeof(lint)*(n+1) );
        memset( last,0,sizeof(lint)*(n+1) );
    }
    int dfs(int x,lint maxf,lint& mincost) {
        if (x==t||maxf==0) return maxf;
        lint ret=0;
        vis[x]=1;
        for (int i=last[x]; i; i=e[i].next)
            if (e[i].c&&dis[e[i].to]+e[i].w==dis[x]&&!vis[e[i].to]) {
                lint f=dfs(e[i].to,min(e[i].c,maxf-ret),mincost);
                mincost+=f*e[i].w;
                e[i].c-=f;
                e[e[i].op].c+=f;
                ret+=f;
                if (ret==maxf) break;
            }
        return ret;
    }

    bool change() {
        lint mn=inf;
        for (int i=0; i<=t; i++)
            if (vis[i])
                for (int j=last[i]; j; j=e[j].next)
                    if (!vis[e[j].to]&&e[j].c) mn=min(mn,-dis[i]+e[j].w+dis[e[j].to]);
        if (mn==inf) return 0;
        for (int i=0; i<=t; i++)
            if (vis[i]) dis[i]+=mn;
        return 1;
    }

    void zkw( int _s,int _t,lint& maxflow,lint& mincost ) {
        s = _s; t = _t;
        do {
            for (int i=0; i<=t; i++) vis[i]=0;
            lint dt = 0;
            while ( dt = dfs(s,inf,mincost)) {
                maxflow += dt;
                for (int i=0; i<=t; i++) vis[i]=0;
            }
        } while (change());
    }
}
int a[maxn][maxn];
int gcd( int x,int y ){
    if( !y ) return x;
    return  gcd( y,x%y );
}
int main(){
    int ca,tt = 0;
    scanf("%d",&ca);
    while(ca--){
        e1.clear();e2.clear();
        int n,m,res = 0;
        scanf("%d%d",&n,&m);
        int lcm = n*m/gcd(n,m);
        for( int i = 1;i <= n;i++ ){
            for( int j = 1;j <= m;j++ ){
                scanf("%d",&a[i][j]);
                res += a[i][j];
            }
        }
        S = 0,T = 50;
        MFMC::init(T);
        int ans = inf;
        int hi = 20*n*m;
        for( int i = 1;i <= n;i++ ){
            for( int j = 1;j <= m;j++ ){
                MFMC::add( i,j+20,a[i][j],-1 );
                MFMC::add( i,j+20,inf,1 );
            }
        }
        for( int i = 1;i <= n;i++ ){
            MFMC::add( S,i,0,0 );
        }
        for( int i = 1;i <= m;i++ ){
            MFMC::add( i+20,T,0,0 );
        }
        int mincost = 0,maxflow =0 ;
        for( int c = 0;c <= hi;c += lcm ){
            if(c) {
                for (int i :e1 ) {
                    MFMC::e[i].c += lcm/n;
                }
                for (int i :e2 ) {
                    MFMC::e[i].c += lcm/m;
                }
            }
            MFMC::zkw( S,T,maxflow,mincost );
            ans = min( ans,res+mincost );
        }
        printf("Case %d: %d\n",++tt,ans);
    }
    return 0;
}

下面是普通zkw不在殘餘網絡上跑 的TLE版本,不過更適合作爲模板

mincost 和 maxflow 都在MFMC中清空了。

#include <bits/stdc++.h>
using namespace std;
typedef int lint;
const int maxn = 25;
const int inf = 0x3f3f3f3f;
int S,T;
namespace MFMC{
    const int N = 505;
    const int M = 100005;
    const lint inf = 0x3f3f3f3f;
    struct edge {
        int from,to,c,op,next;
        lint w;
    } e[M];
    int vis[N],last[N],tot;
    lint dis[N];
    int s,t;
    void add(int u,int v,int c,lint w) {
        e[++tot].from=u;
        e[tot].to=v;
        e[tot].c=c;
        e[tot].w=w;
        e[tot].op=tot+1;
        e[tot].next=last[u];
        last[u]=tot;

        e[++tot].from=v;
        e[tot].to=u;
        e[tot].c=0;
        e[tot].w=-w;
        e[tot].op=tot-1;
        e[tot].next=last[v];
        last[v]=tot;

    }
    void init( int n ) {
        tot = 0;
        memset( vis,0,sizeof(lint)*(n+1) );
        memset( dis,0,sizeof(lint)*(n+1) );
        memset( last,0,sizeof(lint)*(n+1) );
    }
    int dfs(int x,lint maxf,lint& mincost) {
        if (x==t||maxf==0) return maxf;
        lint ret=0;
        vis[x]=1;
        for (int i=last[x]; i; i=e[i].next)
            if (e[i].c&&dis[e[i].to]+e[i].w==dis[x]&&!vis[e[i].to]) {
                lint f=dfs(e[i].to,min(e[i].c,maxf-ret),mincost);
                mincost+=f*e[i].w;
                e[i].c-=f;
                e[e[i].op].c+=f;
                ret+=f;
                if (ret==maxf) break;
            }
        return ret;
    }

    bool change() {
        lint mn=inf;
        for (int i=0; i<=t; i++)
            if (vis[i])
                for (int j=last[i]; j; j=e[j].next)
                    if (!vis[e[j].to]&&e[j].c) mn=min(mn,-dis[i]+e[j].w+dis[e[j].to]);
        if (mn==inf) return 0;
        for (int i=0; i<=t; i++)
            if (vis[i]) dis[i]+=mn;
        return 1;
    }

    void zkw( int _s,int _t,lint& maxflow,lint& mincost ) {
        s = _s; t = _t;
        mincost = maxflow = 0;
        do {
            for (int i=0; i<=t; i++) vis[i]=0;
            lint dt = 0;
            while ( dt = dfs(s,inf,mincost)) {
                maxflow += dt;
                for (int i=0; i<=t; i++) vis[i]=0;
            }
        } while (change());
    }
}
int a[maxn][maxn];
int gcd( int x,int y ){
    if( !y ) return x;
    return  gcd( y,x%y );
}
int main(){
    int ca,tt = 0;
    scanf("%d",&ca);
    while(ca--){
        int n,m,res = 0;
        scanf("%d%d",&n,&m);
        int lcm = n*m/gcd(n,m);
        for( int i = 1;i <= n;i++ ){
            for( int j = 1;j <= m;j++ ){
                scanf("%d",&a[i][j]);
                res += a[i][j];
            }
        }
        S = 0,T = 50;
        int ans = inf;
        int hi = 20*n*m;
        int mincost = 0,maxflow =0 ;
        for( int c = 0;c <= hi;c += lcm ){
            MFMC::init(T);
            for( int i = 1;i <= n;i++ ){
                for( int j = 1;j <= m;j++ ){
                    MFMC::add( i,j+20,a[i][j],-1 );
                    MFMC::add( i,j+20,inf,1 );
                }
            }
            for( int i = 1;i <= n;i++ ){
                MFMC::add( S,i,c/n,0 );
            }
            for( int i = 1;i <= m;i++ ){
                MFMC::add( i+20,T,c/m,0 );
            }
            MFMC::zkw( S,T,maxflow,mincost );
            ans = min( ans,res+mincost );
        }
        printf("Case %d: %d\n",++tt,ans);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章