• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
kito's blog
Dreaming away.
博客园    首页    新随笔    联系   管理    订阅  订阅

cogs 2398 切糕 最小割

cogs 2398 切糕
题解:
若没有D的限制,我们建模应该是这样的。
1
跑一个最小割即可。
有了D的限制,那么存在点对(i,j)要求i,j的割边距离差不能超过D,假设D是1,图应该是这样。
2
如果割断了v(1,1)是不会割断v(2,3)的,我们假设割断的是v(2,3)那么此时会有一条路从v(2,2)的后继点到达v(1,1)的后继点,此时整张图还没有被割断,而每行边我们只割断一条,所以这不是一个合法的割,所以不会割断v(2,3)。
所以就是让第i行编号为k的点向第j行编号为k-D的点连一条INF的边就好。
code

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define fcl fclose(stdin); fclose(stdout); return 0
void Read(int& x){
	char ch; while(ch=getchar(),ch<'0'||ch>'9');
	x=ch-'0'; while(ch=getchar(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
int P,Q,R,D;
int v[50][50][50];
int S,T;
struct EDGE{
	int to,next,flow;
}edge[700010];
int head[64010],tot=1;
inline void AddEdge(int a,int b,int c){
	edge[++tot].to=b;
	edge[tot].flow=c;
	edge[tot].next=head[a];
	head[a]=tot;
}
inline void Add(int a,int b,int c){
	AddEdge(a,b,c); AddEdge(b,a,0);
}
#define ty (edge[x].to)
int cur[64010],dis[64010],Que[64010];
const int INF=0x7f7f7f7f;
bool Bfs(){
	memset(dis,0x7f,(T+1)<<2); dis[S]=0;
	int s=1,t=1,u; Que[1]=S;
	while(s<=t){
		u=Que[s++];
		for(int x=head[u];x;x=edge[x].next)
			if(edge[x].flow&&dis[ty]==INF)
				dis[ty]=dis[u]+1,Que[++t]=ty;
	}
	return dis[T]!=INF;
}
int Dfs(int u,int a){
	if(u==T||a==0) return a;
	int f2=0,f;
	for(int& x=cur[u];x;x=edge[x].next){
		if(edge[x].flow&&dis[ty]==dis[u]+1){
			f=Dfs(ty,min(a,edge[x].flow));
			edge[x].flow-=f; edge[x^1].flow+=f;
			f2+=f; a-=f;
			if(a==0) break;
		}
	}
	return f2;
}
int MinCut(){
	int res=0;
	while(Bfs()){
		memcpy(cur,head,(T+1)<<2);
		res+=Dfs(S,INF);
	}
	return res;
}
int main(){
	freopen("nutcake.in","r",stdin);
	freopen("nutcake.out","w",stdout);
	
	scanf("%d%d%d%d",&P,&Q,&R,&D);
	int i,j,k,p;
	for(k=1;k<=R;++k)
		for(i=1;i<=P;++i)
			for(j=1;j<=Q;++j)
				Read(v[i][j][k]);
	S=P*Q*R+1,T=S+1;
	for(i=1;i<=P;++i){
		for(j=1;j<=Q;++j){
			p=(i-1)*Q+j;
			Add(S,p,INF);
			for(k=1;k<R;++k,p+=P*Q)
				Add(p,p+P*Q,v[i][j][k]);
			Add(p,T,v[i][j][R]);
			for(k=1+D,p=(i-1)*Q+j+D*P*Q;k<=R;++k,p+=P*Q){
				if(i>1) Add(p,(i-2)*Q+j+(k-D-1)*P*Q,INF);
				if(i<P) Add(p,i*Q+j+(k-D-1)*P*Q,INF);
				if(j>1) Add(p,(i-1)*Q+j-1+(k-D-1)*P*Q,INF);
				if(j<Q) Add(p,(i-1)*Q+j+1+(k-D-1)*P*Q,INF);
			}
		}
	}
	printf("%d\n",MinCut());
	fcl;
}
posted @ 2017-07-08 06:42  kito  阅读(159)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3