BZOJ 1001: [BeiJing2006]狼抓兔子

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 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

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 }

 

 

posted @ 2017-02-18 21:00  sigongzi  阅读(220)  评论(0编辑  收藏  举报