思路:
首先最大流显然,朴素建模显然.
但是边数是\(O((a+b)n^2)\)会爆炸.
因此我们得考虑优化.
注意到题目中的一个条件,也就是说每一个区域都是正方形.
因此我们设\(f[i][j][k]\)表示左上角坐标为\((i,j)\),边长为\(2^k\)的正方形区域,那么我们就可以用\(O(1)\)个这种正方形区域来完全覆盖所求的区域.
这样就可以过了.具体见代码.
#include<cstdio> #include<cstring> #include<cctype> #include<iostream> #include<algorithm> #define INF 0x3f3f3f3f struct MaxflowSolver{ static const int V=100000; static const int E=1000010; int head[V],next[E],end[E],flow[E],ind; int gap[V],d[V],stk[V],top,cur[V]; inline void reset(){ind=top=0,memset(head,-1,sizeof head);} inline void addedge(int a,int b,int f){int q=ind++;end[q]=b,next[q]=head[a],head[a]=q,flow[q]=f;} inline void make(int a,int b,int f){addedge(a,b,f),addedge(b,a,0);} inline void bfs(int T){ static int q[V];int fr=0,ta=0; memset(gap,0,sizeof gap),memset(d,-1,sizeof d),++gap[d[T]=0],q[ta++]=T; while(fr^ta){ int i=q[fr++];for(int j=head[i];j!=-1;j=next[j])if(d[end[j]]==-1)++gap[d[end[j]]=d[i]+1],q[ta++]=end[j]; } } inline int Maxflow(int S,int T,int cnt){ int i,Min,ins,u=S,res=0;bfs(T),memcpy(cur,head,sizeof cur); while(d[S]<cnt){ if(u==T){ for(Min=INF,i=0;i<top;++i)if(Min>flow[stk[i]])Min=flow[stk[i]],ins=i; for(res+=Min,i=0;i<top;++i)flow[stk[i]]-=Min,flow[stk[i]^1]+=Min; u=end[stk[top=ins]^1]; } if(u!=T&&!gap[d[u]-1])break; bool find=0; for(int&j=cur[u];j!=-1;j=next[j])if(flow[j]&&d[u]==d[end[j]]+1){find=1,ins=j;break;} if(find)cur[u]=stk[top++]=ins,u=end[ins]; else{ Min=cnt;for(int j=head[u];j!=-1;j=next[j])if(flow[j]&&d[end[j]]<Min)Min=d[end[j]],cur[u]=j; if(!--gap[d[u]])break;++gap[d[u]=Min+1]; if(u!=S)u=end[stk[--top]^1]; } }return res; } }Stg; #define N 61 #define M 61 int in[N][M],out[N][M]; int left[N][M][6],right[N][M][6]; int len[61]; int main(){ int n,m,a,b;scanf("%d%d%d%d",&n,&m,&a,&b);register int i,j,k; int cnt=0; Stg.reset(); int S=++cnt,T=++cnt; int x;for(i=1;i<=n;++i)for(j=1;j<=m;++j)scanf("%d",&x),Stg.make(in[i][j]=++cnt,out[i][j]=++cnt,x); for(i=1;i<=n;++i)for(j=1;j<=m;++j)left[i][j][0]=++cnt,right[i][j][0]=++cnt; for(i=1;i<=n;++i)for(j=1;j<=m;++j)Stg.make(left[i][j][0],in[i][j],INF); for(i=1;i<=n;++i)for(j=1;j<=m;++j)Stg.make(out[i][j],right[i][j][0],INF); for(k=1;(1<<k)<=n&&(1<<k)<=m;++k)for(i=1;i+(1<<k)-1<=n;++i)for(j=1;j+(1<<k)-1<=m;++j){ left[i][j][k]=++cnt; Stg.make(left[i][j][k],left[i][j][k-1],INF); Stg.make(left[i][j][k],left[i+(1<<(k-1))][j][k-1],INF); Stg.make(left[i][j][k],left[i][j+(1<<(k-1))][k-1],INF); Stg.make(left[i][j][k],left[i+(1<<(k-1))][j+(1<<(k-1))][k-1],INF); right[i][j][k]=++cnt; Stg.make(right[i][j][k-1],right[i][j][k],INF); Stg.make(right[i+(1<<(k-1))][j][k-1],right[i][j][k],INF); Stg.make(right[i][j+(1<<(k-1))][k-1],right[i][j][k],INF); Stg.make(right[i+(1<<(k-1))][j+(1<<(k-1))][k-1],right[i][j][k],INF); } for(i=2;i<=60;++i)len[i]=len[i>>1]+1; int x1,y1,x2,y2,l; while(a--){ scanf("%d%d%d%d%d",&x,&x1,&y1,&x2,&y2);l=len[x2-x1+1]; Stg.make(S,++cnt,x); Stg.make(cnt,left[x1][y1][l],INF); Stg.make(cnt,left[x1][y2-(1<<l)+1][l],INF); Stg.make(cnt,left[x2-(1<<l)+1][y1][l],INF); Stg.make(cnt,left[x2-(1<<l)+1][y2-(1<<l)+1][l],INF); } while(b--){ scanf("%d%d%d%d%d",&x,&x1,&y1,&x2,&y2);l=len[x2-x1+1]; Stg.make(++cnt,T,x); Stg.make(right[x1][y1][l],cnt,INF); Stg.make(right[x1][y2-(1<<l)+1][l],cnt,INF); Stg.make(right[x2-(1<<l)+1][y1][l],cnt,INF); Stg.make(right[x2-(1<<l)+1][y2-(1<<l)+1][l],cnt,INF); } printf("%d",Stg.Maxflow(S,T,cnt)); return 0; }