1. 程式人生 > >BZOJ1001 BJOI2006 狼抓兔子

BZOJ1001 BJOI2006 狼抓兔子

個數 push class math 技術 mes inpu load output

Description


現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形:

技術分享圖片

左上角點為(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 }

BZOJ1001 BJOI2006 狼抓兔子