BZOJ 1001: [BeiJing2006]狼抓兔子
1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 20587 Solved: 5135
[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新加数据一组,可能会卡掉从前可以过的程序。
————————————————————————————题解
大概刷题就是从第一页一道一道点下去做吧
网络流跑不动,对偶图求最短路,最短路用线段树优化dij
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <set> 7 #include <vector> 8 #include <string.h> 9 #include <cmath> 10 #include <stack> 11 #include <map> 12 #define siji(i,x,y) for(int i=(x);i<=(y);++i) 13 #define gongzi(j,x,y) for(int j=(x);j>=(y);--j) 14 #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i) 15 #define sigongzi(j,x,y) for(int j=(x);j>(y);--j) 16 #define inf 0x3f3f3f3f 17 //#define ivorysi 18 #define mo 97797977 19 #define hash 974711 20 #define base 47 21 #define pss pair<string,string> 22 #define MAXN 5000 23 #define fi first 24 #define se second 25 #define pii pair<int,int> 26 #define esp 1e-8 27 typedef long long ll; 28 using namespace std; 29 struct node { 30 int to,next,val; 31 }edge[8000005]; 32 int n,m; 33 int si,ti; 34 int head[2000005],sumedge; 35 int dist[2500005],vis[2000005],dis[2500005]; 36 int k,tree[4500005]; 37 void add(int u,int v,int c) { 38 edge[++sumedge].to=v; 39 edge[sumedge].next=head[u]; 40 edge[sumedge].val=c; 41 head[u]=sumedge; 42 } 43 void addtwo(int u,int v,int c) { 44 add(u,v,c); 45 add(v,u,c); 46 } 47 void init() { 48 scanf("%d%d",&n,&m); 49 si=1; 50 ti=(n-1)*(m-1)*2+2; 51 int c; 52 53 xiaosiji(j,1,m) { 54 scanf("%d",&c); 55 addtwo(j*2+1,ti,c); 56 } 57 xiaosiji(i,2,n) { 58 xiaosiji(j,1,m) { 59 scanf("%d",&c); 60 addtwo((i-1)*(m-1)*2+j*2+1,(i-2)*(m-1)*2+j*2,c); 61 } 62 } 63 xiaosiji(j,1,m) { 64 scanf("%d",&c); 65 addtwo((n-2)*(m-1)*2+j*2,si,c); 66 } 67 xiaosiji(i,1,n) { 68 siji(j,1,m) { 69 scanf("%d",&c); 70 if(j==1) addtwo(si,(i-1)*(m-1)*2+j*2,c); 71 else if(j==m) addtwo(ti,i*(m-1)*2+1,c); 72 else addtwo((i-1)*(m-1)*2+j*2,(i-1)*(m-1)*2+j*2-1,c); 73 } 74 } 75 xiaosiji(i,1,n) { 76 xiaosiji(j,1,m) { 77 scanf("%d",&c); 78 addtwo((i-1)*(m-1)*2+j*2,(i-1)*(m-1)*2+j*2+1,c); 79 } 80 } 81 } 82 void change(int x) { 83 int t=(1<<k)+x-1; 84 t>>=1; 85 while(t>0) { 86 tree[t]=dist[tree[t<<1]] < dist[tree[t<<1|1]] ? tree[t<<1] : tree[t<<1|1]; 87 t>>=1; 88 } 89 } 90 void dijkstra() { 91 siji(z,1,ti) {//之前是xiaosiji,但是dis[ti]可能没有刷成新值 92 int u=tree[1]; 93 vis[u]=1; 94 //printf("%d\n",u); 95 for(int i=head[u];i;i=edge[i].next) { 96 int v=edge[i].to; 97 if(vis[v]) continue; 98 if(dist[v] > dist[u]+edge[i].val) { 99 dist[v]=dist[u]+edge[i].val; 100 change(v); 101 } 102 } 103 dis[u]=dist[u]; 104 dist[u]=inf; 105 change(u); 106 107 } 108 } 109 void solve() { 110 init(); 111 while((1<<k) < ti) ++k; 112 siji(i,2,(1<<k)) dist[i]=inf; 113 siji(i,1,(1<<k)) { 114 tree[(1<<k)+i-1]=i; 115 } 116 gongzi(i,(1<<k)-1,1) { 117 tree[i]=dist[tree[i<<1]] < dist[tree[i<<1|1]] ? tree[i<<1] : tree[i<<1|1]; 118 } 119 dijkstra(); 120 printf("%d\n",dis[ti]); 121 } 122 int main(int argc, char const *argv[]) 123 { 124 #ifdef ivorysi 125 freopen("f1.in","r",stdin); 126 #endif 127 solve(); 128 return 0; 129 }