bzoj1001 [BeiJing2006]狼抓兔子 (最小割)

1001: [BeiJing2006]狼抓兔子

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

输出一个整数,表示参与伏击的狼的最小数量.

 

 

最小割裸题啊(笑);

然而N*M=1e6,T了(可能吧);

我们注意到该图形态固定;

而割掉一条边等价于从该边一侧走到另一侧,经过一条权值为该边边权的路;

所以直接转成最短路即可;

(n==1 和 m==1 要特判

AC GET☆DAZE

 

↓代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<algorithm>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #define N 2000039
 10 #define M 6000039
 11 #define ll long long
 12 #define inf 0x3f3f3f3f
 13 using namespace std;
 14 struct edge
 15 {
 16     int to,w,next;
 17 }net[M];
 18 int head[N],S,T,tot=0,dis[N];
 19 bool inq[N];
 20 queue<int> que;
 21 void add(int u,int v,int w)
 22 {
 23     net[++tot].to=v,net[tot].w=w,net[tot].next=head[u],head[u]=tot;
 24     net[++tot].to=u,net[tot].w=w,net[tot].next=head[v],head[v]=tot;
 25 }
 26 void spfa()
 27 {
 28     memset(dis,inf,sizeof(dis)); 
 29     memset(inq,0,sizeof(inq));
 30     que.push(S),dis[S]=0,inq[S]=1;
 31     int a,b;
 32     while(!que.empty())
 33     {
 34         a=que.front();
 35         que.pop();
 36         for(b=head[a];b!=-1;b=net[b].next)
 37         {
 38             if(dis[a]+net[b].w<dis[net[b].to])
 39             {
 40                 dis[net[b].to]=dis[a]+net[b].w;
 41                 if(!inq[net[b].to])
 42                 {
 43                     inq[net[b].to]=1;
 44                     que.push(net[b].to);
 45                 }
 46             }
 47         }
 48         inq[a]=0;
 49     }
 50 }
 51 int main()
 52 {
 53     memset(head,-1,sizeof(head));
 54     int n,m,ans=inf,a,b,c;
 55     scanf("%d%d",&n,&m);
 56     S=0,T=2*(n-1)*(m-1)+1;
 57     if(n==1)
 58     {
 59         for(a=1;a<m;a++)
 60         {
 61             scanf("%d",&b);
 62             ans=min(ans,b);
 63         }
 64         printf("%d",ans);
 65         return 0;
 66     }
 67     if(m==1)
 68     {
 69         for(a=1;a<n;a++)
 70         {
 71             scanf("%d",&b);
 72             ans=min(ans,b);
 73         }
 74         printf("%d",ans);
 75         return 0;
 76     }
 77     for(a=1;a<m;a++)
 78     {
 79         scanf("%d",&b);
 80         add(S,a,b);
 81     }
 82     for(a=2;a<n;a++)
 83     {
 84         for(b=1;b<m;b++)
 85         {
 86             scanf("%d",&c);
 87             add(((a-1)*2-1)*(m-1)+b,(a-1)*2*(m-1)+b,c);
 88         }
 89     }
 90     for(a=1;a<m;a++)
 91     {
 92         scanf("%d",&b);
 93         add(((n-1)*2-1)*(m-1)+a,T,b);
 94     }
 95     for(a=1;a<n;a++)
 96     {
 97         scanf("%d",&b);
 98         add((a*2-1)*(m-1)+1,T,b);
 99         for(b=2;b<m;b++)
100         {
101             scanf("%d",&c);
102             add((a-1)*2*(m-1)+(b-1),(a*2-1)*(m-1)+b,c);
103         }
104         scanf("%d",&b);
105         add(S,(a*2-1)*(m-1),b);
106     }
107     for(a=1;a<n;a++)
108     {
109         for(b=1;b<m;b++)
110         {
111             scanf("%d",&c);
112             add((a-1)*2*(m-1)+b,(a*2-1)*(m-1)+b,c);
113         }
114     }
115     spfa();
116     printf("%d",dis[T]);
117     return 0;
118 }
bzoj1001

 

posted @ 2017-08-18 22:48  Sinogi  阅读(210)  评论(0编辑  收藏  举报