矩阵 - 最小割

题目大意:有一个N*M的网格,在每个格子填入1~9中的某一个。有若干限制形如某相邻的两个数字和不能超过x,最大化每个格子的数值之和。
题解:
直接做不好维护;考虑切糕,a+b<=x等价于a<=x-b即(10-x)+a<=(10-b)也就是x’+a<=b’。这个黑白染色之后黑格子的链翻转就可以了,注意只能从a连向b’来限制。最后求的是最大,每个位置都用10减去,最后再算回来即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<queue>
#define MXN 55
#define N (MXN*MXN*13)
#define M 1000010//MXN*MXN*58
#define INF 214748354//(INT_MAX/10-10)
#define gc getchar()
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*((n)+1))
#define clr(a,n) memset(a,0,sizeof(int)*((n)+1))
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define build_edge(u,v,f) add_edge(u,v,f),add_edge(v,u,0)//,debug(u)sp,debug(v)sp,debug(f)ln
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
    int to,pre,resf;
}e[M];int cur[N],h[N],lev[N],etop,P[MXN][MXN][12],col[MXN][MXN],ban[MXN][MXN][12];queue<int> q;
inline int add_edge(int u,int v,int f) { return e[++etop].to=v,e[etop].resf=f,e[etop].pre=h[u],h[u]=etop; }
inline int bfs(int s,int t)
{
    while(!q.empty()) q.pop();
    clr(lev,t),lev[s]=1,q.push(s);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=h[x],y;i;i=e[i].pre)
            if(!lev[y=e[i].to]&&e[i].resf)
                lev[y]=lev[x]+1,q.push(y);
    }
    return lev[t];
}
int dfs(int s,int t,int a)
{
    if(s==t||!a) return a;int flow=0,f;
    for(int &i=cur[s];i;i=e[i].pre)
        if(lev[e[i].to]==lev[s]+1&&(f=dfs(e[i].to,t,min(a,e[i].resf)))>0)
        {   e[i].resf-=f,e[((i-1)^1)+1].resf+=f,a-=f,flow+=f;if(!a) break;  }
    return flow;
}
inline int dinic(int s,int t,int flow=0)
{   while(bfs(s,t)) cpy(cur,h,t),flow+=dfs(s,t,INF);return flow;    }
#define v 10
int main()
{
    int n=inn(),m=inn(),c=0,s,t;
    rep(i,1,n) rep(j,1,m) rep(k,1,v) P[i][j][k]=++c;
    s=++c,t=++c;rep(i,1,n) rep(j,1,m) col[i][j]=(i+j)&1;
    rep(i,1,n) rep(j,1,m) rep(k,1,v-1)
        if(!col[i][j]) build_edge(P[i][j][k],P[i][j][k+1],v-(k));
        else build_edge(P[i][j][k],P[i][j][k+1],v-(v-k));
    rep(i,1,n) rep(j,1,m) build_edge(s,P[i][j][1],INF),build_edge(P[i][j][v],t,INF);
    rep(i,1,n-1) rep(j,1,m)
    {
        int x=v-inn();
        rep(k,1,v-1)
            if(!col[i][j]) build_edge(P[i][j][k],P[i+1][j][max(min(k+x,v),1)],INF);
            else build_edge(P[i+1][j][k],P[i][j][max(min(k+x,v),1)],INF);
    }
    rep(i,1,n) rep(j,1,m-1)
    {
        int x=v-inn();
        rep(k,1,v-1)
            if(!col[i][j]) build_edge(P[i][j][k],P[i][j+1][max(min(k+x,v),1)],INF);
            else build_edge(P[i][j+1][k],P[i][j][max(min(k+x,v),1)],INF);
    }
    return !printf("%d\n",v*n*m-dinic(s,t));
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82463156