bzoj 1001 [BeiJing2006]狼抓兔子
[BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 26066 Solved: 6612
[Submit][Status][Discuss]
Description
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
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个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
HINT
2015.4.16新加数据一组,可能会卡掉从前可以过的程序。
Source
题解:平面图最小割转最短路。
1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<cstdlib> 7 8 #define N 2000007 9 #define ll long long 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 int n,m,nm; 20 struct data 21 { 22 int to,next,v; 23 }e[4*N]; 24 int dis[N],q[N],head[N]; 25 bool flag[N]; 26 int ne; 27 28 void insert(int u,int v,int w) 29 { 30 ne++; 31 e[ne].to=v; 32 e[ne].v=w; 33 e[ne].next=head[u]; 34 head[u]=ne; 35 ne++; 36 e[ne].to=u; 37 e[ne].v=w; 38 e[ne].next=head[v]; 39 head[v]=ne; 40 } 41 void spfa() 42 { 43 memset(dis,0x3f,sizeof(dis)); 44 int t=0,w=1; 45 dis[0]=q[w]=0;flag[0]=1; 46 while(t!=w) 47 { 48 int u=q[t++]; 49 flag[u]=0; 50 if(t==N)t=0; 51 for(int i=head[u];i;i=e[i].next) 52 { 53 int v=e[i].to; 54 if(dis[v]>dis[u]+e[i].v) 55 { 56 dis[v]=dis[u]+e[i].v; 57 if(flag[v]==0) 58 { 59 flag[v]=1; 60 q[w++]=v; 61 if(w==N)w=0; 62 } 63 } 64 } 65 } 66 } 67 int main() 68 { 69 n=read(),m=read(); 70 nm=(n*m-m-n+1)<<1; 71 int x; 72 for(int j=1;j<m;j++) 73 { 74 scanf("%d",&x); 75 insert(j,nm+1,x); 76 } 77 for(int i=1;i<n-1;i++) 78 { 79 for(int j=1;j<m;j++) 80 { 81 scanf("%d",&x); 82 insert((i<<1)*(m-1)+j,((i<<1)-1)*(m-1)+j,x); 83 } 84 } 85 for(int j=1;j<m;j++) 86 { 87 scanf("%d",&x); 88 insert(0,((n<<1)-3)*(m-1)+j,x); 89 } 90 for(int i=0;i<n-1;i++) 91 for(int j=1;j<=m;j++) 92 { 93 scanf("%d",&x); 94 if(j==1)insert(0,(i<<1)*(m-1)+m,x); 95 else if(j==m)insert((i<<1|1)*(m-1),nm+1,x); 96 else insert((i<<1)*(m-1)+j-1,(i<<1)*(m-1)+j+m-1,x); 97 } 98 for(int i=0;i<n-1;i++) 99 for(int j=1;j<m;j++) 100 { 101 scanf("%d",&x); 102 insert((i<<1|1)*(m-1)+j,(i<<1)*(m-1)+j,x); 103 } 104 spfa(); 105 printf("%d",dis[nm+1]); 106 }