1. 程式人生 > >bzoj 3144 [Hnoi2013]切糕【最小割+dinic】

bzoj 3144 [Hnoi2013]切糕【最小割+dinic】

當前 printf sizeof left 需要 bzoj str 容量 dfs

都說了是‘切’糕所以是最小割咯
建圖:

  • 每個點向下一層連容量為這個點的val的邊,S向第一層連容量為inf的邊,最後一層向T連容量為自身val的邊,即割斷這條邊相當於\( f(i,j) \)選擇了當前層
  • 第i層的每個點向第i+d層的與其相鄰點\( \left | x_i-x_{i+d} \right |+\left | y_i-y_{i+d} \right |==1 \)連容量為inf的邊,即割斷i+d這層以及以下各層需要inf的費用,相當於防止相鄰點的\( f(i,j) \)值選擇差大於等於d的情況

dinic的dfs不要再寫錯了

#include<iostream>
#include<cstdio>
#include<queue> #include<cstring> using namespace std; const int N=45,inf=1e9,D=100005; int p,q,r,d,s,t,v[N][N][N],id[N][N][N],cnt=1,h[D],le[D]; struct qwe { int ne,to,va; }e[D<<1]; int read() { int r=0; char p=getchar(); while(p>‘9‘||p<‘0‘) p=getchar(); while
(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r; } void add(int u,int v,int w) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; e[cnt].va=w; h[u]=cnt; } void ins(int u,int v,int w) { add(u,v,w); add(v,u,0); } bool bfs() { queue<int
>q; memset(le,0,sizeof(le)); le[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=h[u];i;i=e[i].ne) if(!le[e[i].to]&&e[i].va) {//cout<<e[i].to<<" "<<le[e[i].to]<<endl; le[e[i].to]=le[u]+1;//cout<<e[i].to<<" "<<le[e[i].to]<<endl; q.push(e[i].to); } } return le[t]; } int dfs(int u,int val) { if(u==t)//u==t !!! return val; int now=0; for(int i=h[u];i&&now<val;i=e[i].ne)//now<val !!! if(le[u]+1==le[e[i].to]&&e[i].va>0) { int t=dfs(e[i].to,min(val-now,e[i].va));//val-now !!! e[i].va-=t; e[i^1].va+=t; now+=t; } if(!now) le[u]=-1; return now; } int dinic() { int re=0,now; while(bfs()) while(now=dfs(s,inf)) re+=now;//,cout<<now<<endl; return re; } int main() { p=read(),q=read(),r=read(),d=read(); 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++) v[i][j][k]=read(),id[i][j][k]=(i-1)*p*q+(j-1)*q+k; for(int i=1;i<r;i++) for(int j=1;j<=p;j++) for(int k=1;k<=q;k++) ins(id[i][j][k],id[i+1][j][k],v[i][j][k]); for(int j=1;j<=p;j++) for(int k=1;k<=q;k++) ins(s,id[1][j][k],inf); for(int j=1;j<=p;j++) for(int k=1;k<=q;k++) ins(id[r][j][k],t,v[r][j][k]); for(int i=d+1;i<=r;i++) for(int j=1;j<=p;j++) for(int k=1;k<=q;k++) { if(j!=1) ins(id[i][j][k],id[i-d][j-1][k],inf); if(j!=p) ins(id[i][j][k],id[i-d][j+1][k],inf); if(k!=1) ins(id[i][j][k],id[i-d][j][k-1],inf); if(k!=q) ins(id[i][j][k],id[i-d][j][k+1],inf); } printf("%d\n",dinic()); return 0; }

bzoj 3144 [Hnoi2013]切糕【最小割+dinic】