BZOJ 1001: [BeiJing2006]狼抓兔子

这只是一道朴素的网络流

求出单位时间里最多能同时通过的兔子数就是需要的狼的数目

用了朴素的dinic方法

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define g getchar()
#define inf 0x3f3f3f3f
#define maxe 6000005
#define maxn 1000005
using namespace std;

struct re{int v,w,next;}ed[maxe];
int e,n,m,ans;
int head[maxn],dui[maxn],pd[maxn];
inline int read(){                                        //朴素的读入优化
	int x=0,f=1;char ch=g;
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=g;}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=g;}
	return x*f;
}

void ins(int x,int y,int w){                             //朴素的链式前向星
	ed[++e].v=y;ed[e].next=head[x];ed[e].w=w;head[x]=e;
	ed[++e].v=x;ed[e].next=head[y];ed[e].w=w;head[y]=e;
}
inline int min(int x,int y){                             //朴素的较小值
	return x<y?x:y;
}
void init(){                                             //朴素的init
	n=read(),m=read();
	for(int i=1;i<=n;++i)
	for(int j=1;j<m;++j){
		int x=read();
		ins(m*(i-1)+j,m*(i-1)+j+1,x);
	}
	for(int i=1;i<n;++i)
	for(int j=1;j<=m;++j){
		int x=read();
		ins(m*(i-1)+j,m*i+j,x);
	}
	for(int i=1;i<n;++i)
	for(int j=1;j<m;++j){
		int x=read();
		ins(m*(i-1)+j,m*i+j+1,x);
	}
}
bool bfs(){                                             //朴素的BFS判断是否存在增广路
	int tou=1,wei=1;
	dui[tou]=1;
	memset(pd,-1,sizeof(pd));
	pd[1]=0;
	for(;tou<=wei;++tou){
		int u=dui[tou];
		for(int i=head[u];i;i=ed[i].next){
			if(ed[i].w&&pd[ed[i].v]<0){
				dui[++wei]=ed[i].v;
				pd[ed[i].v]=pd[u]+1;
			}
		}
	}
	return pd[n*m]!=-1;
}
int dfs(int x,int w){                                   //朴素的DFS求增广路径的流量
	if(x==n*m)return w;
	int used=0,left;
	for(int i=head[x];i;i=ed[i].next){
		if(ed[i].w&&pd[ed[i].v]==pd[x]+1){
			left=w-used;
			left=dfs(ed[i].v,min(left,ed[i].w));
			ed[i].w-=left;
			ed[i%2?i+1:i-1].w+=left;        //反向边加上相应流量
			used+=left;
			if(used==w)return w;
		}
	}
	if(!used)pd[x]=-1;
	return used;
}
int main(){                                             //仅有3行的主程序
	init();
	while(bfs())ans+=dfs(1,inf);
	printf("%d",ans);return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值