Description
Input
第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。Output
仅包含一个整数,表示在合法基础上最小的总不和谐值。
Sample Input
2 2 2
1 6 1 6 1 2 6 2 6Sample Output
6
HINT
最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1
Solution
拆成 \(R\) 层点,源点向第一层连边,最后一层向汇点连边
中间每一层 \(i\) 号点向下一层的 \(i\) 号点连边,流量为不和谐度 那么这样每一个纵轴就只会被切一个地方,满足题目要求 对于特殊限制,我们只要在被限制的点往上 \(D\) 层的四周的点连流量为 \(inf\) 的边即可,这样限制了四周的纵轴不能在 往上\(D\) 层之上切 最小割就代表切开,直接跑就好了#include#define ui unsigned int#define ll long long#define db double#define ld long double#define ull unsigned long longconst int MAXP=50+5,MAXN=64000+10,MAXM=MAXN*5+10,inf=0x3f3f3f3f;int P,Q,R,D,e=1,beg[MAXN],cur[MAXN],G[MAXP][MAXP][MAXP],level[MAXN],vis[MAXN],clk,s,t,to[MAXM<<1],nex[MAXM<<1],cap[MAXM<<1],dr[4][2]={ {0,1},{1,0},{-1,0},{0,-1}};std::queue q;template inline void read(T &x){ T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w;}template inline void write(T x,char ch='\0'){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(ch!='\0')putchar(ch);}template inline void chkmin(T &x,T y){x=(y inline void chkmax(T &x,T y){x=(y>x?y:x);}template inline T min(T x,T y){return x inline T max(T x,T y){return x>y?x:y;}inline int id(int x,int y,int z){ return (z-1)*P*Q+(x-1)*Q+y;}inline void insert(int x,int y,int z){ to[++e]=y; nex[e]=beg[x]; beg[x]=e; cap[e]=z; to[++e]=x; nex[e]=beg[y]; beg[y]=e; cap[e]=0;}inline bool bfs(){ memset(level,0,sizeof(level)); level[s]=1; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); for(register int i=beg[x];i;i=nex[i]) if(cap[i]&&!level[to[i]])level[to[i]]=level[x]+1,q.push(to[i]); } return level[t];}inline int dfs(int x,int maxflow){ if(x==t||!maxflow)return maxflow; vis[x]=clk; int res=0; for(register int &i=cur[x];i;i=nex[i]) if((vis[x]^vis[to[i]])&&cap[i]&&level[to[i]]==level[x]+1) { int f=dfs(to[i],min(cap[i],maxflow)); res+=f; cap[i]-=f; cap[i^1]+=f; maxflow-=f; if(!maxflow)break; } return res;}inline int Dinic(){ int res=0; while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),res+=dfs(s,inf); return res;}int main(){ read(P);read(Q);read(R);read(D); for(register int k=1;k<=R;++k) for(register int i=1;i<=P;++i) for(register int j=1;j<=Q;++j)read(G[i][j][k]); s=P*Q*R+1,t=s+1; for(register int i=1;i<=P;++i) for(register int j=1;j<=Q;++j) for(register int k=1;k<=R;++k) { if(k==1)insert(s,id(i,j,k),inf); if(k!=R)insert(id(i,j,k),id(i,j,k+1),G[i][j][k]); else insert(id(i,j,k),t,G[i][j][k]); } for(register int k=D+1;k<=R;++k) for(register int i=1;i<=P;++i) for(register int j=1;j<=Q;++j) for(register int p=0;p<4;++p) { int dx=i+dr[p][0],dy=j+dr[p][1]; if(dx<1||dx>P||dy<1||dy>Q)continue; insert(id(i,j,k),id(dx,dy,k-D),inf); } write(Dinic(),'\n'); return 0;}