BZOJ 3894 文理分科

如图建图
1336138-20190213193738136-51443036.jpg

#include <cstdio>
#include <queue>
#include <algorithm>

using std::queue;
using std::min;

const int INF=1034567890;
const int MAXN=111;
const int MAXM=111;
const int MAXV=3*MAXN*MAXM;
const int MAXE=14*MAXN*MAXM;

int dx[4]={0, 0, 1, -1};
int dy[4]={1, -1, 0, 0};

int N, M;

bool Norm(int i, int j){
    return i>=1 && i<=N && j>=1 && j<=M;
}

int A[MAXN][MAXM], B[MAXN][MAXM], As[MAXN][MAXM], Bs[MAXN][MAXM];

struct Vert{
    int FE;
    int Lev, Bfn;
} V[MAXV];

int Vcnt;
int Sink, Sour;
int P[MAXN][MAXM], Ap[MAXN][MAXM], Bp[MAXN][MAXM];

struct Edge{
    int y, f, next, neg;
} E[MAXE<<1];

int Ecnt;

void addE(int a, int b, int f){
    ++Ecnt;
    E[Ecnt].y=b;E[Ecnt].f=f;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;E[Ecnt].neg=Ecnt+1;
    ++Ecnt;
    E[Ecnt].y=a;E[Ecnt].f=0;E[Ecnt].next=V[b].FE;V[b].FE=Ecnt;E[Ecnt].neg=Ecnt-1;
}

int BFN;
queue<int> Q;

bool BFS(int at=Sour){
    ++BFN;
    V[at].Lev=1;
    Q.push(at);
    V[at].Bfn=BFN;
    while(!Q.empty()){
        at=Q.front();Q.pop();
        for(int k=V[at].FE, to;k;k=E[k].next){
            if(E[k].f<=0)   continue;
            to=E[k].y;
            if(V[to].Bfn==BFN)  continue;
            V[to].Lev=V[at].Lev+1;
            Q.push(to);
            V[to].Bfn=BFN;
        }
    }
    return V[Sink].Bfn==BFN;
}

int DFS(int at=Sour, int inc=INF){
    if(at==Sink || inc<=0)  return inc;
    int ret=0, out;
    for(int k=V[at].FE, to;k;k=E[k].next){
        if(E[k].f<=0)   continue;
        to=E[k].y;
        if(V[to].Lev!=V[at].Lev+1)  continue;
        out=DFS(to, min(E[k].f, inc));
        inc-=out;ret+=out;
        E[k].f-=out;E[E[k].neg].f+=out;
    }
    if(inc>0)   V[at].Lev=-1;
    return ret;
}

int DINIC(){
    int ret=0;
    while(BFS())    ret+=DFS();
    return ret;
}

int main(){
    
    scanf("%d%d", &N, &M);
    
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            scanf("%d", &A[i][j]);
    
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            scanf("%d", &B[i][j]);
    
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            scanf("%d", &As[i][j]);
    
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            scanf("%d", &Bs[i][j]);
    
    Sour=++Vcnt;Sink=++Vcnt;
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j){
            P[i][j]=++Vcnt;
            Ap[i][j]=++Vcnt;
            Bp[i][j]=++Vcnt;
        }
    
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j){
            addE(Sour, P[i][j], A[i][j]);
            addE(Sour, Ap[i][j], As[i][j]);
            addE(P[i][j], Sink, B[i][j]);
            addE(Bp[i][j], Sink, Bs[i][j]);
            addE(Ap[i][j], P[i][j], INF);
            addE(P[i][j], Bp[i][j], INF);
            for(int k=0;k<4;++k){
                if(Norm(i+dx[k], j+dy[k])){
                    addE(Ap[i][j], P[i+dx[k]][j+dy[k]], INF);
                    addE(P[i+dx[k]][j+dy[k]], Bp[i][j], INF);
                }
            }
        }
    
    int Sum=0;
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            Sum+=A[i][j]+B[i][j]+As[i][j]+Bs[i][j];
    
    int Ans=DINIC();
    
    printf("%d\n", Sum-Ans);
    
    return 0;
}

/*
3 4
13 2 4 13
7 13 8 12
18 17 0 5
8 13 15 4
11 3 8 11
11 18 6 5
1 2 3 4
4 2 3 2
3 1 0 4
3 2 3 2
0 2 2 1
0 2 4 4

*/

转载于:https://www.cnblogs.com/Pickupwin/p/BZOJ3894.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值