bzoj 1001 [BeiJing2006]狼抓兔子

[BeiJing2006]狼抓兔子

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

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 }

 

posted @ 2018-01-05 13:26  Kaiser-  阅读(185)  评论(0编辑  收藏  举报