当前位置: 代码迷 >> 综合 >> 最小割 [HNOI 2013]切糕
  详细解决方案

最小割 [HNOI 2013]切糕

热度:56   发布时间:2023-12-08 15:09:27.0

     传送门

     读了好久才看懂题。在这个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]);elseadd(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(){;}

  相关解决方案