BZOJ 1001: [BeiJing2006]狼抓兔子

Fancy posted @ 2015年7月08日 22:57 in BZOJ , 308 阅读

题目大意面对下面这样一个网格的地形:

左上角点为(1,1),右下角点为(N,M)(上图中N=3,M=2).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。

 

裸的最大流

学长说他直接用最大流过不了,我也不明白。。。

#include<bits/stdc++.h>
#define LINK(x)	for(int e=head[x];e;e=E[e].next)
using namespace std;
const int N=1000010;
const int M=10000010;
const int inf=1e9;
struct Edge{int to,rest,next;}E[M];
queue<int> Q;
int head[N],ds[N];
int n,m,x,S,T,ecnt=1;
inline void AddEdge(int x,int y,int r)
{
	++ecnt;E[ecnt].to=y,E[ecnt].rest=r,E[ecnt].next=head[x];head[x]=ecnt;
	++ecnt;E[ecnt].to=x,E[ecnt].rest=r,E[ecnt].next=head[y];head[y]=ecnt;
}
inline bool BFS()
{
	for(int i=S;i<=T;i++)  ds[i]=-1;
	Q.push(S);ds[S]=0;
	while(!Q.empty())
	{
		int x=Q.front(); Q.pop();
		LINK(x)	if(E[e].rest && ds[E[e].to]==-1)
		  ds[E[e].to]=ds[x]+1,Q.push(E[e].to);
	}
	return ds[T]>-1;
}
inline int DFS(int x,int flow)
{
	if(x==T)  return flow;
	int a=0,b;
	LINK(x)	if(E[e].rest&&ds[E[e].to]==ds[x]+1)
	{
		b=DFS(E[e].to, min(flow-a,E[e].rest));
		E[e].rest-=b, E[e^1].rest+=b;
		a+=b;
		if(a==flow)	return flow;
	}
	if(a==0)  ds[x]=-1;
	return a;
}
inline int dinic()
{
	int ans=0;
	while(BFS())  ans+=DFS(S,inf);
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	S=1;T=n*m;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<m;j++)
	  scanf("%d",&x),AddEdge((i-1)*m+j,(i-1)*m+j+1,x);
	for(int i=1;i<n;i++)
	  for(int j=1;j<=m;j++)
	  scanf("%d",&x),AddEdge((i-1)*m+j,i*m+j,x);
	for(int i=1;i<n;i++)
	  for(int j=1;j<m;j++)
	  scanf("%d",&x),AddEdge((i-1)*m+j,i*m+j+1,x);
	printf("%d",dinic());
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter