BZOJ 2132 圈地计划

题目传送门

分析:

首先A和B2选1就是一组矛盾关系

然后相邻的两个格子选相同的也是一种矛盾

我们可以把格子染成黑白颜色,像国际象棋棋盘那样

对于黑格子,与S连容量为A的边,与T连容量为B的边

对于白格子,与S连容量为B的边,与T连容量为A的边

然后相邻格子,连容量为两个格子C之和的边

考虑正确性

同一个格子,A和B必须割一个

对于相邻格子,选相同和额外收益必须割一个

没有问题

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>

#define maxt 10005
#define maxn 105
#define INF 0x3f3f3f3f

using namespace std;

inline int getint()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    return num*flag;
}

int n,m,S,T;
int fir[maxt],nxt[20*maxt],to[20*maxt],cap[20*maxt],cnt;
int a[maxn][maxn],b[maxn][maxn],c[maxn][maxn];
int col[maxn][maxn];
long long ans;
int h[maxt];

inline int getid(int i,int j){return (i-1)*m+j;}
inline void newnode(int u,int v,int w)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;}
inline void insert(int u,int v,int w)
{newnode(u,v,w),newnode(v,u,0);}

inline bool bfs()
{
    memset(h,-1,sizeof h);
    queue<int>Q;h[S]=0,Q.push(S);
    while(!Q.empty())
    {
        int u=Q.front();Q.pop();
        for(int i=fir[u];i;i=nxt[i])
            if(cap[i]&&!~h[to[i]])h[to[i]]=h[u]+1,Q.push(to[i]);
    }
    return ~h[T];
}

inline int dfs(int u,int flow)
{
    if(u==T)return flow;
    int used=0;
    for(int i=fir[u];i;i=nxt[i])
        if(cap[i]&&h[to[i]]==h[u]+1)
        {
            int w=flow-used;
            w=dfs(to[i],min(cap[i],w));
            cap[i]-=w,cap[i^1]+=w,used+=w;
            if(used==flow)return flow;
        }
    if(!used)h[u]=-1;
    return used;
}

inline void dinic(){while(bfs())ans-=dfs(S,INF);}

int main()
{
    n=getint(),m=getint();S=n*m+1,T=S+1;cnt=1;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans+=a[i][j]=getint();
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans+=b[i][j]=getint();
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)c[i][j]=getint();
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)col[i][j]=(i+j)&1;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    {
        if(col[i][j])swap(a[i][j],b[i][j]);
        insert(S,getid(i,j),a[i][j]),insert(getid(i,j),T,b[i][j]);
        if(i>1)ans+=c[i][j],insert(getid(i,j),getid(i-1,j),c[i][j]+c[i-1][j]);
        if(i<n)ans+=c[i][j],insert(getid(i,j),getid(i+1,j),c[i][j]+c[i+1][j]);
        if(j>1)ans+=c[i][j],insert(getid(i,j),getid(i,j-1),c[i][j]+c[i][j-1]);
        if(j<m)ans+=c[i][j],insert(getid(i,j),getid(i,j+1),c[i][j]+c[i][j+1]);
    }
    dinic();
    printf("%lld\n",ans);
}
View Code

猜你喜欢

转载自www.cnblogs.com/Darknesses/p/12006133.html