【BZOJ1001】狼抓兔子

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 7530  Solved: 1724
[Submit][Status]

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

 

Source

分析:根据题意很容易想到是(1,1)到(n,m)最大流,但最多会有10^6点,普通的会TLE。本屌丝当然也没招~~搜了题解,原来是2008周冬的集训队论文里提到的平面图的最大流——>最小割——>对偶图的最短路,于是可以最短路做,我用的是dijkstra+heap

题解:关于平面图的最大流详见周冬的论文(AH的oier呢好骄傲~~~),这里我只想提一下,根据平面图的定义,几乎所有最大流问题都可以这样做,当然前提是容易判断各个面,目前我见到的只是这种网格网络流,求大神分享其他的……

然后这题只剩建图了:大家自己在草稿纸画画就行了,我是将s点定为0,t点定为(n-1)*(m-1)*2+1(因为里面有(n-1)*(m-1)*2的三角形面),然后就是按顺序给里面的三角形编号,从左到右从上到下编号。然后有左边界或者下边界的连向s,有上边界或者右边界的连向t,中间的处理画画图谢谢式子就行了,具体看我程序

注意:1、建图的时候左下角会连2次s,右上角会连2次t,所以要判重,取两条边中最小的

   2、特判m=1或n=1,ans是输入的数中的最小值

 

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<queue>
  4 #include<cstring>
  5 #include<vector>
  6 using namespace std;
  7 const int maxn=1000;
  8 const int maxm=1000;
  9 const int inf=1000000000;
 10 struct heap
 11 {
 12     int d,u;
 13     bool operator < (const heap& x) const
 14     {
 15         return d>x.d;
 16     }
 17 };
 18 priority_queue<heap> q;
 19 struct wjmzbmr
 20 {
 21     int to,data;
 22 };
 23 vector<wjmzbmr> g[(maxn-1)*(maxm-1)*2+50];
 24 int n,m,d[(maxn-1)*(maxm-1)*2+50],f[(maxn-1)*(maxm-1)*2+50];
 25 void ins(int a,int b,int w)
 26 {
 27     g[a].push_back({b,w});
 28     g[b].push_back({a,w});
 29 }
 30 int main()
 31 {    scanf("%d%d",&n,&m);
 32     for(int i=0;i<=(maxn-1)*(maxm-1)*2+1;++i) g[i].clear();
 33     if(n==1&&m==1) 
 34     {
 35     printf("0");
 36     return 0;
 37     }
 38     if(n==1)
 39     {
 40         int s=inf,x;
 41         for(int i=1;i<m;++i) scanf("%d",&x),s=min(s,x);
 42         printf("%d",s);
 43         return 0; 
 44     }
 45     if(m==1)
 46     {
 47         int s=inf,x;
 48         for(int i=1;i<n;++i) scanf("%d",&x),s=min(s,x);
 49         printf("%d",s);
 50         return 0; 
 51     }
 52     int s=0,t=(n-1)*(m-1)*2+1,a=inf,b=inf;
 53     for(int i=1;i<=n;++i)
 54         for(int j=1;j<m;++j) 
 55             {
 56                 int x;
 57                 scanf("%d",&x);
 58                 if(i==1&&j==m-1)
 59                 {
 60                     a=min(x,a);
 61                     continue;
 62                 }
 63                 if(i==n&&j==1)
 64                 {
 65                     b=min(x,b);
 66                     continue;
 67                 }
 68                 if(i==1) ins(j,t,x);
 69                 if(i==n) ins((n-2)*(m-1)*2+m-1+j,s,x);
 70                 if(i!=1&&i!=n) ins(2*(i-2)*(m-1)+m-1+j,2*(i-1)*(m-1)+j,x);
 71                 
 72             }
 73     for(int i=1;i<=n-1;++i)
 74         for(int j=1;j<=m;++j)
 75         {
 76             int x;
 77             scanf("%d",&x);
 78                 if(i==1&&j==m)
 79                 {
 80                     a=min(x,a);
 81                     continue;
 82                 }
 83                 if(i==n-1&&j==1)
 84                 {
 85                     b=min(x,b);
 86                     continue;
 87                 }
 88             if(j==1) ins(s,(i-1)*2*(m-1)+m,x);
 89             if(j==m) ins(t,(i-1)*2*(m-1)+m-1,x);
 90             if(j!=1&&j!=m) ins((i-1)*2*(m-1)+j-1,(i-1)*2*(m-1)+m-1+j,x);
 91         }
 92     for(int i=1;i<=n-1;++i)
 93         for(int j=1;j<=m-1;++j)
 94         {
 95             int x;
 96             scanf("%d",&x);
 97             ins((i-1)*2*(m-1)+j,(i-1)*(m-1)*2+m-1+j,x);
 98         }
 99     ins(m-1,t,a);ins(t-m+1,0,b);
100     memset(f,0,sizeof(f));
101     for(int i=s;i<=t;++i) d[i]=inf;d[s]=0;
102     while(!q.empty())q.pop();
103     q.push({0,s});
104     while(!q.empty())
105     {
106         heap x=q.top();q.pop();
107         if(f[x.u]==1) continue;
108         f[x.u]=1;
109         for(int i=0;i<g[x.u].size();++i)
110             if(d[x.u]+g[x.u][i].data<d[g[x.u][i].to])
111             {
112                 d[g[x.u][i].to]=d[x.u]+g[x.u][i].data;
113                 q.push({d[g[x.u][i].to],g[x.u][i].to});
114             }
115     }
116     printf("%d",d[t]);
117     return 0;
118 }
View Code
posted @ 2013-12-22 21:04  Chellyutaha  阅读(699)  评论(0编辑  收藏  举报