BZOJ3144: [Hnoi2013]切糕
【传送门:BZOJ3144】
简要题意:
题解:
最小割经典问题
我们构造一个P*Q*(R+1)的点阵,用(i,j,k)表示一个点 那么(i,j,k)->(i,j,k+1) 的流量为原图中(i,j,k)的不和谐值。 S向所有底层连无穷边,所有顶层向T连无穷边。 那么(i,j,k) -> (i,j,k+1)被割表示f(i,j)=k
同时我们让(i,j,k)->(i',j',k-D)连一条无穷边,就能保证相邻两个不超过D了。
参考代码:
#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; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚