最小割 [HNOI 2013]切糕

     传送门

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

原文地址:https://www.cnblogs.com/QTY2001/p/7632759.html