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()); }