BZOJ1001 BJOI2006 狼抓兔子
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=3,M=4).有以下三种类型的道路
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只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦。
Input:
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
Output:
输出一个整数,表示参与伏击的狼的最小数量.
Solution
转化为网络流,把每个有直接连边的点之间连一条权为X的边,然后跑一边最大流即可。
1 //Writer : Hsz %WJMZBMR%tourist%hzwer 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 #include<set> 9 #include<stack> 10 #include<vector> 11 #include<cstdlib> 12 #include<algorithm> 13 #define LL long long 14 using namespace std; 15 const int S=1,N=1000001,M=6000001,inf=0x3fffffff; 16 int to[M],val[M],nxt[M],h[N],head[N],ecnt=1,T; 17 int n,m; 18 void add(int bg,int ed,int v) { 19 to[++ecnt]=ed; 20 nxt[ecnt]=head[bg]; 21 val[ecnt]=v; 22 head[bg]=ecnt; 23 } 24 void ins(int bg,int ed,int x) { 25 add(bg,ed,x); 26 add(ed,bg,x); 27 } 28 bool bfs() { 29 memset(h,-1,sizeof h); 30 h[S]=0; 31 queue<int>q; 32 q.push(S); 33 while(!q.empty()) { 34 int u=q.front(); 35 q.pop(); 36 for(int i=head[u]; i; i=nxt[i]) { 37 if(val[i]&&h[to[i]]==-1) { 38 h[to[i]]=h[u]+1; 39 q.push(to[i]); 40 } 41 } 42 } 43 return h[T]!=-1; 44 } 45 int dfs(int x,int f) { 46 if(x==T) return f; 47 int tp,used=0; 48 for(int i=head[x]; i; i=nxt[i]) { 49 if(h[to[i]]==h[x]+1&&val[i]) { 50 tp=dfs(to[i],min(f-used,val[i])); 51 val[i]-=tp; 52 val[i^1]+=tp; 53 used+=tp; 54 if(used==f) return f; 55 } 56 } 57 if(!used ) h[x]=-1; 58 return used; 59 } 60 int maxflow; 61 void dinic() { 62 maxflow=0; 63 while(bfs()) { 64 maxflow+=dfs(1,inf); 65 } 66 } 67 int main() { 68 int x; 69 cin>>n>>m; 70 T=n*m; 71 for(int i=1; i<=n; i++) { 72 for(int j=1; j<m; j++) { 73 scanf("%d",&x); 74 ins(m*(i-1)+j,m*(i-1)+j+1,x);//建图过程。加的反边也应权为x,因为反向也可能跑兔子。 75 } 76 } 77 for(int i=1; i<n; i++) { 78 for(int j=1; j<=m; j++) { 79 scanf("%d",&x); 80 ins(m*(i-1)+j,m*(i)+j,x); 81 } 82 } 83 for(int i=1; i<n; i++) { 84 for(int j=1; j<m; j++) { 85 scanf("%d",&x); 86 ins(m*(i-1)+j,m*(i)+j+1,x); 87 } 88 } 89 dinic(); 90 cout<<maxflow; 91 return 0; 92 }
我是咸鱼。转载博客请征得博主同意Orz