【Portal: BZOJ3144】
Brief title:
answer:
Minimum cut classical problem
We construct a lattice of P*Q*(R+1) and use (i,j,k) to represent a point, then the flow of (i,j,k)->(i,j,k+1) is the original The dissonance value of (i,j,k) in the graph. S connects infinite edges to all bottom layers, and all top layers connect infinite edges to T. Then (i,j,k) -> (i,j,k+1) is cut to indicate f(i,j)=k
At the same time, we let (i,j,k)->(i',j',kD) connect an infinite edge, and we can ensure that the two adjacent ones do not exceed D.
Reference Code:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #define INF 1<<31-1 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct node { int x,y,c,next,other; }a[1100000];int len,last[110000]; void ins(int x,int y,int c) { int k1 = ++ len, k2 = ++ len; a[k1].x =x;a[k1].y=y;a[k1].c= c; a[k1].next=last[x];last[x]=k1; a[k2].x=y;a[k2].y=x;a[k2].c=0; a[k2].next=last[y];last[y]=k2; a[k1].other=k2; a[k2].other=k1; } int h[110000],list[110000],st,ed; bool bt_h() { memset(h,0,sizeof(h));h[st]=1; list[1]=st; int head=1,tail=2; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(a[k].c>0&&h[y]==0) { h[y]=h[x]+1; list[tail++]=y; } } head++; } if(h[ed]==0) return false; else return true; } int cur[110000]; int findflow(int x,int f) { if(x==ed) return f; int s=0,t; for(int k=cur[x];k;k=a[k].next) { int y=a[k].y; if(a[k].c>0&&f>s&&h[y]==(h[x]+1)) { t=findflow(y,min(a[k].c,f-s)); s+=t; a[k].c-=t;a[a[k].other].c+=t; if(a[k].c>0) cur[x]=k; if(f==s) break; } } if(s==0) h[x]=0; return s; } int v[41][41][41],id[41][41][41]; int dx[5]={0,1,-1,0,0}; int dy[5]={0,0,0,1,-1}; int main() { int P=read(),Q=read(),R=read(),D=read(); int z=0; for(int i=1;i<=P;i++) for(int j=1;j<=Q;j++) id[0][i][j]=++z; for(int i=1;i<=R;i++) for(int j=1;j<=P;j++) for(int k=1;k<=Q;k++) v[i][j][k]=read(),id[i][j][k]=++z; len=0;memset(last,0,sizeof(last)); st=0;ed=z+1; for(int i=0;i<=R;i++) { if(i==R) for(int j=1;j<=P;j++) for(int k=1;k<=Q;k++) ins(id[i][j][k],ed,INF); if(i==0) for(int j=1;j<=P;j++) for(int k=1;k<=Q;k++) ins(st,id[i][j][k],INF); else for(int j=1;j<=P;j++) for(int k=1;k<=Q;k++) ins(id[i-1][j][k],id[i][j][k],v[i][j][k]); } for(int i=D+1;i<=R;i++) { for(int j=1;j<=P;j++) { for(int k=1;k<=Q;k++) { for(int t=1;t<=4;t++) { int tx=j+dx[t],ty=k+dy[t]; if(tx<1||ty<1||tx>P||ty>Q) continue; ins(id[i][j][k],id[i-D][tx][ty],999999999); } } } } int ans=0; while(bt_h()==true) { for(int i=st;i<=ed;i++) cur[i]=last[i]; ans += findflow(st,INF); } printf("%d\n",ans); return 0; }