读了好久才看懂题。在这个p,q,r的长方体里,每个纵轴选一个点,共有p*q个,相邻的格点纵坐标不相差d。
把点权下放到边。S->第一层->第二层……->第R层->T(边权就是刚才下放的点权)
但是又有了那个平滑度,可以向他周围四个位置比它低d层的点建一个流量为inf的边,就可以保证。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> #define inf 100000000 using namespace std; int p,q,r,v[45][45][45],d,id[45][45][45],cnt,e=2; int S=0,T,adj[100000],dep[100000],g[4][2]={0,1,1,0,0,-1,-1,0}; struct node { int v,next,l; } a[2000000]; void add(int u,int v,int l) { a[e].v=v;a[e].l=l;a[e].next=adj[u];adj[u]=e++; a[e].v=u;a[e].l=0;a[e].next=adj[v];adj[v]=e++; } int bfs() { memset(dep,0,sizeof(dep)); queue<int> q; q.push(S); dep[S]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=adj[x];i;i=a[i].next) { int to=a[i].v; if(!dep[to]&&a[i].l) { dep[to]=dep[x]+1; q.push(to); if(to==T)return 1; } } } return 0; } int dfs(int x,int len) { if(x==T)return len; int tmp=len,k; for(int i=adj[x];i;i=a[i].next) { int to=a[i].v; if(tmp&&a[i].l&&dep[to]==dep[x]+1) { k=dfs(to,min(a[i].l,tmp)); if(!k) { dep[to]=0; continue; } a[i].l-=k; a[i^1].l+=k; tmp-=k; } } return len-tmp; } int yjn() { freopen("nutcake.in","r",stdin); freopen("nutcake.out","w",stdout); scanf("%d%d%d%d",&p,&q,&r,&d);T=p*q*r+1; for(int i=1;i<=r;i++) for(int j=1;j<=p;j++) for(int k=1;k<=q;k++) scanf("%d",&v[i][j][k]),id[i][j][k]=++cnt; for(int i=1;i<=r;i++)for(int j=1;j<=p;j++)for(int k=1;k<=q;k++) { if(i==1) add(S,id[i][j][k],v[i][j][k]); else add(id[i-1][j][k],id[i][j][k],v[i][j][k]); if(i==r) add(id[i][j][k],T,inf); if(i>d) { for(int l=0;l<=3;l++) { int x=j+g[l][0],y=k+g[l][1]; if(x<1||x>p||y<1||y>q)continue; add(id[i][j][k],id[i-d][x][y],inf); } } } int ans=0; while(bfs()) ans+=dfs(S,inf); cout<<ans; } int qty=yjn(); int main(){;}